Now that we know how to parse
and use submitted data,
we finally can do something,
which we were not able to do before.
We can now actually handle the submission
of a form here on our own server.
So with our own server-side code.
And that, of course,
means that we could now also handle more complex forms
as we built them before in the forms section of this course
but it is something we'll come back to later
once we build more realistic projects.
For the moment, let's instead dive in deeper,
and let's do more interesting things
that we can do now with NodeJS and Express
that we couldn't do before
with just HTML, CSS and browser-side JavaScript.
And the next thing I wanna do
is I wanna store the usernames,
which are submitted by users in an actual text file.
We could also store it in a database
but that requires a bit more knowledge.
We'll gain that throughout the course as well.
But starting with a text file is good enough for now,
and shows us how we can access the file system
of our server with Node and Express code.
And for this, my goal is to add a new data folder here.
Name is up to you but I'll call it data,
and in that folder, I'll add a new file,
the users.json file.
Now, I'm using this .json extension
to make it clear that the content
in this file should follow this JSON format,
which I already did show you here
when we had a look at the package.json file.
I'm using this format instead of a regular text file
since reading and writing JSON data
is very easy for machines, for computers,
and therefore, we can easily store complex data,
like a list of usernames in such a file
without having to write a bunch
of extra logic for then parsing that data correctly
and so on.
At the moment though, this users.json file is empty,
at least almost empty.
The only thing I'll add here
is opening and closing square brackets.
So like an array but an empty array.
And also just that.
No variable name or anything like that
because this is not JavaScript code,
this is just a text file following a certain text format,
and hence, I really just have that empty array in here.
And then I'll save users.json and close that file.
Now I wanna open that file here
in the post method and add a username to that array
so that the array doesn't stay empty.
And to achieve this,
we'll use another package.
Again, a package that's built into NodeJS,
so not a package that we have to install separately.
For this, I'll require it,
and the package I wanna require is the fs package,
which stands for file system.
Now, I'll require it first before I require Express,
though the order actually doesn't matter
but it is the convention
to always require core NodeJS packages
that are built into NodeJS first
before you require any possible third-party packages
you might be using.
And then again, I store the content of that package,
which in this case, will again be an object
in a variable or constant.
The constant name is up to you
but since this is the file system package,
I'll give that constant the same name.
And now we can use the object stored in this constant
to perform file system operations.
Instead of console.logging the username,
I now wanna use that fs package
to then open this file, this users.json file,
which we have in the data folder,
and write data into it.
For that, we have the writeFileSync method here,
and it's important that you use the sync method
since that will perform the operation instantly,
which is what we want here.
And to writeFileSync,
you now have to pass a path
to the file where this data should be written to.
Now, that is the users.json file in the data folder,
so in that data subfolder,
and hence, the full path includes both the folder name
and the file name.
Now, to construct that path in a way
that will work on all operating systems,
I will require another core package
that's built into Node,
and that's the path package,
which helps us with constructing paths.
I'll also store this here in a constant.
The path package makes it easy
to construct complete paths
that will work on all operating systems
with minimal effort.
And we can use this required path package here now
to construct our filePath,
which I'll store in a separate constant
by using path.join.
And then here we now want
to join multiple fragments together
that describe the overall path
where the data should be stored in.
Now, the important thing here
is that this path actually has to be an absolute path.
And therefore, we have to start with the path
of our project directory.
Now, we could look this up
and see which path that is on our operating system
but it's far easier
if we use a special globally available variable
that is exposed by NodeJS.
And that's the __dirname variable.
And it's important that you have two underscores
at the beginning.
This name might look strange
but it is a valid JavaScript variable name,
and it's a built-in variable or constant
that actually holds the absolute path
to this project directory.
And now we can add multiple arguments
by separating them with commas
to build a more complex path,
which starts at the project directory
but then dives into the data folder,
hence I add data as a string
as a second argument.
And then opens the users.json file.
So users.json is the last argument here.
And that constructs now a path
that works cross platform on all operating systems
to that file.
And to writeFileSync, I'll now pass this filePath.
Now, that's part one.
That tells the file system package
where the file is into which it should write.
But we also have to define the data
that should be written into that file.
And that should be the existing list in that file
plus the username we entered here.
So therefore, we actually, first of all,
need to read that file
so that we can extract existing data out of it.
Then we need to add userName to that existing data,
and then write the updated existing data back into the file.
Hence, actually before writing the file,
I will use the fs package to read a file,
again readFileSync is the correct method here.
And I wanna read the file in that filePath.
Here we don't need any extra argument.
Instead we can now store the fileData in a new constant.
And that will be the raw data read from that file.
And that will not be a JavaScript object or array,
instead, it will be the file content interpreted as text.
So even if it looks like an array to us humans,
it will be treated as text that contains square brackets.
So to work with it, we need to transform it,
and for that, I'll add another constant,
existingUsers, which should be my parsed file data
so that text content,
which follows the JSON format actually translated
into a JavaScript object or array.
And NodeJS has a built-in helper object
that offers us methods
that help us with that transformation.
And that's the JSON object, all uppercase.
This object has two methods, parse and stringify,
and parse is the method which we need
if we wanna translate some text
that contains data in the JSON format
into a raw JavaScript object or array.
And here, I wanna parse the fileData
so that text data which we read from the file.
With that, we're reading that data
and we're translating it into a JavaScript array
with which we can work.
And then as a next step,
we can use the existingUsers array,
and actually add our username to that list.
And we can do that with the push method.
The push method is a default method,
which we can call on any array in JavaScript,
which allows us to add a new item to that array.
So which appends a new item at the end of the array.
And here I wanna push userName into existingUsers.
So that updates existingUsers by adding a new item.
And if you wonder why we can use const
if we change this value,
then the answer is that we do change the underlying value
in memory but we never assign
a brand new value to existingUsers.
We would only do that
if we use the equal sign operator again.
If I try to assign a new empty array,
that would be invalid.
If I edit the existing array in memory,
that is allowed.
It's a bit more complex
and a bit more advanced JavaScript knowledge here
but it is something worth mentioning.
This code, at the end, should work,
and should add our user to that parsed data
which we got from the file.
Now, this alone will not update the file though
because we just read data from it
and then translated it into JavaScript objects or arrays.
Now, to save that updated data back into the file,
we now need to work with existing users
to which we pushed this new userName
and save that back into the file with writeFileSync.
However, just as readFileSync returned just some raw text,
writeFileSync wants some raw text.
So if I try to pass existingUsers here,
that would fail because that's not raw text,
instead, that will be a JavaScript array.
And that is not something we can store like that.
Instead, we need to translate it back
and we can do this by again using JSON,
this helper object, and now the stringify method.
To stringify, we can pass JavaScript values,
like objects or arrays or numbers,
and it will translate that into text,
into raw text that follows the JSON format.
So here to stringify,
we can pass existingUsers,
and now that will overall
then save the updated existingUsers
as text back into that file.
Now, that was a lot of work.
I hope the individual steps are clear.
Let's now see whether that works.
For that, we need to save that file,
and then quit the existing running server,
if you have one.
And rerun our server
by again executing app.js with node again.
And then here I'll reload this page
and again add Max Schwarzmueller as a name.
That seems to work.
We got no error here.
And if I now go back here
and open users.json, we see that name here.
And if I now manually go back to the starting page
by erasing that path here,
and I add Manuel and click Submit,
we also should see Manuel here.
So that is being updated.
The old data is preserved, the new name was added
and that's how we can, for example, store data
into a file.
And of course, if we had a portfolio page
with a contact me page
where users can fill out a form to send us a message,
we could be storing these user messages in files
with an approach similar to what we do here.
But here, that's not the end of what I wanna do.
Instead, I now also wanna add a new path,
which we can access with a get request
where we then extract all the data
that's stored in that file,
and where we then send back some HTML content
with a list of all these stored usernames.
If you're feeling like it,
definitely try it on your own first.
In the next lecture, we'll implement it together.