I'm trying to do something that I think is fairly simple, but doesn't seem to be working. I have a .csv file in the same directory as my script file. I want to create an object or an array using the data from the .csv file. How do I access the local file using javascript?
Sorry for the lack of code, but I don't even know which route to go down; I've tried .get and ajax and this plugin but I just don't know what I'm doing. Could someone give me a clear example of how to load the file and print it in a div?
In order to simulate a static file server, you can run an http server using python on the command line. This is necessary to use ajax requests.
python -m SimpleHTTPServer
Or if you have python 3
python -m http.server
Now there are two parts to getting that file to a webpage. 1) make an ajax request, 2) parse the csv. There are many different libraries that implement ajax requests, but in this case you might find the easiest out of the box solution which combines both is d3.js.
d3.csv("filename.csv", function(err, data) {
// csv is parsed into an array of objects, as data
});
Of course this will only work if you are loading your page from localhost.
EDIT:
Make sure you run your http server from the location of your index.html file. then the request you make in the d3.csv function is relative to index. finally, the data is only available inside the callback, and any error message (or null) will be put inside the err argument.
Project
|
+-- index.html
|
+-- data
| |
| \-- dataset.csv
Then the code in index.html would look like
d3.csv("data/dataset.csv", function(err, data) {
if (err) console.log(err) // error messages
console.log(data); // should contain the parsed csv
});
PapaParse() does an excellent job here, for example this will do the job for you:
Papa.parse(file, {
complete: function(results) {
console.log("Finished:", results.data);
}
});
DEMO
Related
I have a folder structure like this
index.html
file.txt
in the index.html I have a script that wants to read the file.txt and assign it to a variable, say x.
async function loadFile(file) {
let text = await file.text();
console.log(text);
return text
}
var x = loadFile("file.txt")
but this returns an error
main.js:35
Uncaught (in promise) TypeError: file.text is not a function
at loadFile (main.js:35:27)
at main.js:39:13
what to do? I just want to assign file.txt content to a variable.
JavaScript in browser doesn't give you direct access to file system.
What you did is just pass a string to your function and call text() on it. Sadly it doesn't work like that.
Here are two workarounds I know of:
1. fetch api
If you have an http server serving your files then you make a request using fetch() to obtain its content in JS. Read the docs here :
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Note that it won't work on pages loaded with file:// URI scheme. You need http(s). If you have python installed run python -m http.server 8000 in directory containing files to be served.
2. FileReader
If the file is to be selected by user as input to a form then you can use FileReader
Have a look these links:
webdev has great explaination for this
https://web.dev/read-files/
also see the docs
https://developer.mozilla.org/en-US/docs/Web/API/FileReader
Sorry for the wording in the question. Probably my biggest issue with this is not knowing how to phrase it correctly, as I've not been able to gleam a single hint of an answer from google.
Using api routes in Next.js I want to serve a data.json file. This works no problem, however I also want to be able to edit this file afterwards and for the api to reflect the updated content. As it stands after building and running if I edit the file the api still returns the old one, hell I can even delete it. I assume this is because Next.js makes a copy of the file at build time, and puts it somewhere in the .next directory(?), haven't been able to find it there though.
Below is a boiled down version of what I'm doing:
/pages
/api
/info.js
/data
/data.json <- file I want to use with the api
pages/api/info.js
export default function (req, res) {
const data = require('../../data/data.json')
// Do stuff
res.status(200).json(data.something)
}
Any guidance on this is very appreciated
Using require to include a file in any Node app will definitely tie the json file to the apps run time or build time.
The feature you describe sounds like static file serving but next caches those files as well.
Try reading the file in the API instead
const fsp = require('fs').promises
export default async function (req, res) {
try {
const file_data = await fsp.readFile('../../data/data.json')
const json_data = JSON.parse(file_data)
// Do stuff
res.status(200).json(data.something)
}
catch (error) {
console.log(error)
res.status(500).json({ error: 'Error reading data' })
}
}
Actual Static files
In development you can probably work around this by triggering rebuilds when static files update.
If you want update the data files independently of a built app, they will probably need to be hosted separately to the Next build. If you are next exporting a completely static site, you might have a place to put the static files already. If not you can serve the data files with another node process, or a web server, or something like S3.
i have some code that reads a csv using d3-fetch. I load my csv in the way:
D3.csv(./mydata.csv).then(function (info) {
Console.log(info);
});
this works fine and gives me my data. But how would i write to this data?
Keep in mind D3 is supposed to be run in a web browser. Web browsers can read files through HTTP but they cannot write files.
A server could write files on a file system it controls. So you would need to write a server endpoint like /editCSV and then make a POST request to it from the browser. Your server could then write the changes to the CSV file.
In order to do this, you need to have control of the server (for example, a Node.js server) that is serving the CSV and the related file.
I currently have a Javascript application that consists of three files:
index.html
app.js
input.json
The input.json file gets referenced several times by the app.js file, in order to render content into divs in the index.html file.
I want to make it so that loading my index.html at http://example.com/myapp can take an externall hosted JSON as the source for app.js to read, like myexample.com/myapp?myhost.com/files/input.json.
Can anybody advise me on how to get this working?
For this to work, you need to enable CORS on myexample.com.
Assuming you are using jQuery. (Take a look at here if you don't want to use jQuery for ajax requests)
$.get('http://myexample.com/myapp?myhost.com/files/input.json')
.done(function(data) {
// use external 'data' here.
})
.fail(function() {
// handle error here
});
I am using jquery templates on both the server-side and client-side. I'm using the jqtpl and express modules on Node.js for the server, and I have jquery and its template plugin for the client.
Wherever possible the client recieves JSON instead of html, and builds the template itself, using the HTML5 history api to change url and allow session navigation. If this isn't possible, the server does the templating instead and sends html.
Both the server and the client have the exact same templates, but the server has them in the form of 12 .html files, and the client has them in the form of an object in a .js file.
Each time I change or add a template, I have to alter the client .js file to be the same, which is a bit of a pain.
What I would like to do is have the .js file dynamically take all of the .html files in my templates folder and compile them into an object. Once I had finished development, this file would be cached, as it no longer needs to look for changes.
Not sure if this answers your question, but if you're interested in having the same templating code on both client and server, you should take a look at weld which would allow you to use the same code on both client and server.
Could you be a bit more clear about what you're doing with regards to the 12 html files vs 1 object on the client?
Code samples would rock, if possible.
What I was looking for was Node's file system module:
http://nodejs.org/docs/v0.4.8/api/fs.html
I used fs.readdir to find all of the template files in the folder, then iterated through the array that produced to read all of its containing files.
var templates = {};
fs.readdir("./templates", function(err, files) {
for(var i = 0, len = files.length; i<len; i++) {
fs.readFile("./templates/" + files[i], function (err, data) {
if (err) {
throw err
}
templates[files[i]] = data;
});
}
}
And then in express:
app.get("/templates.js", function(req, res){
res.header("Content-Type", "text/javascript");
res.end("var templates = { " + JSON.stringify(templates) + " }; ");
});
However, I found that server-side templating was better suited to my needs, and where appropriate, I now send rendered HTML in my JSON responses instead of just data.