And with that,
we can now again send our HTTP request through JavaScript.
For this we again, use the fetch function
and we now, again, need to construct the path
to which we wanna send this request.
If we have a look at our routes,
we see that it's this post route that we wanna reach.
So the path should be /posts/
then the concrete id of the post and then /comments.
So the same path as up here,
but now it should be a post instead of a get request.
So what we can do actually is we can use this path,
which we constructed earlier and copy this down there, here,
and use that.
And again, construct our postId here,
copy this code,
and also add this year to save comment.
Now, to get the postId,
we can actually still reach out
to the load comments button element,
but alternatively,
we can also add that postId to another element
for example, to the form itself.
Here, we could also add data-postid
and also set this = post._id.
So that we have the id of the post
for which we wanna add comments directly on the form.
And then we could use this dataset here
in the comments.js file
and use the commentsFormElement.dataset.postid
to get the post ID.
And then this would send a request here.
However, now sending a request like this
is not enough anymore.
Before this was great
because fetch by default sends a get request
and that is what I did want to do here
in fetch comments for a post.
But now I wanna send a post request instead.
And even though the name fetch doesn't imply it,
the fetch function cannot just be used for fetching data,
but actually for sending any kind of HTTP request,
including post requests.
All you have to do to switch from I get to a post request
is you have to add a second parameter value
to the fetch function after the URL.
And that second value is an object
in which you can now set different properties.
Different properties
the fetch function we'll be looking for
to configure to fetch functions behavior.
For example, you can set a method property,
and this has to be named method
because browser site JavaScript will look for this key
when the fetch function executes.
And by default, this is set to get
so to a string saying, get,
but you can also set it to post,
to instead send up post request.
And that's what I wanna do here.
Now, a post request then also needs the data
that should be sent with it.
And before we didn't have to worry about that
because the browser sent post requests automatically for us.
Now that we are writing our own code,
we also have to add our own data
to the outgoing request here.
And we do this with another field here
and that's the body field.
Here we set the body of the outgoing request.
And that should now be again, data in the JSON format.
Because as mentioned before,
that is the common data format for exchanging data
when using Ajax,
hence here, we wanna send a new JavaScript object
converted to JSON.
So we can create our comment here, for example,
and include a title,
which is our enteredTitle
and the text, which is our enteredText.
And now I wanna convert this object to JSON.
For this, we can use the built in JSON object.
We actually used it before on the server site
in earlier course sections.
It's also a way level here on the browser side,
so in browser site JavaScript code
and this JSON object, which is built into the browser
has two utility methods,
one method for parsing JSON content.
So for converting JSON to raw JavaScript values
and then stringify for doing the opposite.
So for encoding JavaScript values into JSON.
And that's what we need here
because I want to convert my comment,
JavaScript object into JSON, which looks very similar,
but it's not quite the same as you learn before.
You have all these double quotes
and in the end, JSON is just text
formatted in a certain way.
This JavaScript object here is a special object,
a special data type used in our JavaScript execution here.
So it's a different thing.
Now here we converted it.
And now with we configured this request
to actually be a post request.
Now we do send this to our server
and there we now wanna handle this incoming data.
That means that in blockchain.js
so in our server side routes,
we now also wanna work on this post route again.
Up to this point, this post route extracts some data
from the incoming request and from the URL puff,
and then adds a new comment in our MongoDB collection.
And actually that code should still work,
but there is a tiny gotcha here.
When we extract data from the request body,
we currently only do that
if the request body is URL encoded.
You might remember this term.
If you have a look at app.js
where we register some middleware,
we added this URL encoded middleware
for parsing all incoming requests for data
that might be attached to them.
Well, this will work,
but it only looks for data that is URL encoded,
which is the encoding format if a form is submitted.
That's not what is happening here,
we are preventing that default after all,
we are instead sending JSON data.
Now, thankfully express has a built in middleware
that will also parse JSON data though.
All we have to do here is use another middleware
in addition to the URL encoded middleware
and that's express.json also executed as a function here.
This will parse all incoming requests
and see if they are in the JSON format.
And if they are, it will then parse that JSON data for us.
So by adding this middleware,
we are able to handle incoming requests
that were sent by the browser
where a regular form was submitted
and we're able to handle incoming requests
that use the JSON format,
which is to kind of format
we're using for this request here now.
And with that back in our block.js file in our routes here,
this code here actually should still work
because when we use this JSON middleware,
we will still have a req body field
that holds the parsed content off the incoming request.
So this doesn't change.
We just needed to add that middleware
to parse the content in the first place.
The only thing that has to change here now is the response.
I no longer wanna redirect,
instead I now want to send back some data once we're done.
So I wanna send back some JSON data
and here, of course, I'm not fetching any data,
so I don't really need to, well send back any data
that's coming from a database,
but we could send back our object
which has converted to JSON automatically by this method
where we simply set a message to Comment added.
It's up to you, which data you wanna send back.
You could also send back an empty object
to not send back any data at all.
But you wanna send some response
to signal that you're done and that the request was handled.
And now back in comments.js,
we can, of course, again, wait for this response.
Though, actually we don't even have to do that
if we're not really doing anything with the response,
and we're not doing anything here
because the response doesn't contain anything we need,
we of course don't necessarily have to wait for it,
we can just send this request
and forget about it here on the front-end.
The comment should still be added to the database.
So therefore, long story short,
if we save all our files with all these changes made
and we reload this page here, if I add a new comment here,
"Send via Ajax" and I click Save Comment,
we don't get any feedback here.
So that's something we might wanna change.
But if I load my comments, I get it here
though clearly something went wrong
because I only see null null.
So storing the data failed.
Though he got no error here, so the server didn't crash.
Still, something is not working.
We can also confirm this if we manually use the Mongo shell
to have a look at all the comments.
What we see is that here, I got a comment,
but the title and text is missing.
So what's going on here?
Well, actually one important step is missing still.
We did add this middleware here in app.js
to parse incoming JSON data.
But how do these parsing middlewares
work in the first place?
They actually don't try to simply parse
all incoming request bodies and see if it works or not.
Instead, what they do is,
they look at the headers off the incoming requests.
So at some extra metadata, which is attached to them
and that metadata should contain information
about the encoding of the request body.
And if the metadata says that it's URL encoded,
this middleware will become active.
If the metadata says that it's JSON encoded,
this middleware will become active.
If the metadata doesn't say either of the two things,
no middleware.
So none of these two middlewares will become active.
And that's exactly what's happening here.
We didn't set any metadata on this outgoing request
and hence the body isn't actually being parsed
on our backend code.
For the requests sent automatically by the browser.
For example, when a form is submitted,
the browser did set that metadata for us.
Here since we sent the request ourselves,
we have to do that ourselves.
And just to quickly see that
you can go back to the front-end to the developer tools
and there to the Network tab.
And here, if you inspect this second to last request,
which was this post request,
you can see the headers that were attached to the request.
So you can check the request headers.
And in there, you'll see a bunch of metadata,
which is added automatically.
So that's we just metadata automatically added
by the browser for this outgoing request.
But since the browser didn't create the request,
the browser did not add any metadata
describing the kind of content we're sending
and therefore that's something we need to do ourselves.
Here in the front end code in comments.js,
we add an extra piece of configuration
to this fetch function and that's the headers property.
We can set this to a JavaScript object
to define some extra headers, some extra pieces of metadata
that should be attached to the outgoing request.
And this metadata always has a key value format.
You have a header name and then a value for the header.
And whilst you can add any headers of your choice,
there are a bunch of predefined headers,
which are commonly used.
For example, here, what we need to set
is the 'Content-Type' header written like this.
I put it between single quotes because it contains a dash
and without quotes, this would be an invalid property name
here in JavaScript.
So we need the quotes around it.
'Content-Type' is a special header,
which is exactly the header, the app.js file
so these middlewares will look for,
and it was missing thus far.
So now we add it and now after a colon,
we set the value for this 'Content-Type.'
And here we should set this to application/json.
That's a reserved identifier
for a saying that we add JSON data to this request.
So this line here, this header being added
says that this request carries some JSON data.
So now to check this,
let's go back to the Mongo shell quickly
and actually delete this comment here
by executing db.comments.deleteOne
and then I wanna look for the comment
where the id is equal to ObjectId and then this comment.
So now this comment which was broken was deleted.
If we now reload our post page here,
if I add Another comment, another test Sent via Ajax,
and I then load my comments, now the data is here
because now it's stored in the database.
As you can see, if I, again, get all my comments,
because now it was parsed successfully on the backend
because we told our server,
which kind of data was attached to this incoming request
by adding this extra piece of metadata,
this extra header to this outgoing request.
And therefore you can tell it's a bit more worth,
but it's also in the end not too difficult
to send a post request to the server.
And now we are again sending a request behind the scenes
without reloading the page
and we can then handle it on the server
and sent back a response.
Now we're not doing anything
when we get to this response here,
but sending the request works.
So let's now have a look at different options we have
for using the response
and maybe improving the overall user experience
which we have here.