Updating Data on the Server in MEAN Stack
In our previous section, we learned how to update data into the database using our angular app. Our edit and delete buttons were working well. In this section, we will learn about how we can instantly reload our page because after editing the post, the id of that post is shown on the URL, and that is not a good thing.
We are able to update the post, and now there is no need to use the console log on the server. On the frontend in the posts.service.ts file where we send that http request, we got all the data we need to update the post on the frontend too. This is a kind of redundant because the only place where we use the posts is in the root page. In this root page, we always fetch a new copy, but we still need to know how we can locally update the post after getting the success response. We will use the following steps to locally update the data on the server:
1) We will go back to our updatePost() method, where we create the http request. In the subscription of the http request, instead of using the console log statement, we will replace the current version of that post in our posts array with that version. For this, we will clone our post array and store it in a constant in the following way:
2) After doing that, we will search for that old post version by its ID, so we will search for the index in the following way:
The findIndex() method takes a function that will return true if we find the posts we are looking for. So, in this function, we will check whether the post or the Id of the post we are looking in that array is equal to the post.id or not. If it is equal, then we find the index of the post we want to replace.
3) Now, we will replace the post of that index with our new post in the following way:
4) Now, we need to store the values of updatedPosts array into the original posts array in the following way:
5) Now, we also need to tell our app about this update to our app in the following way:
Now, we also want to make sure that if we are on the edit page and we reload, we don't have the blank form again because we failed to fetch the post. We do fail because if we reload, all our state is lost, and the app restarts. Therefore, our posts array in the service will be empty because we only fetch posts from the server with the getPosts() method, which is only called in the post list component, but if we reload on the page, we would not have visited the post list component yet.
6) So, therefore we also need to get that single post data from the server on the page. We will do this by recycling the getPost() method in the post.service.ts to not get the posts from our local array of posts but to get it from the server. So, we will go back to our js file, and here we will add a new route that will be a get request.
7) This method will reach out to our database and find a post with the id presented in the URL. For that, we will use our postmodel and there we have a findById() method. We will pass the id as an argument, and mongoose will have a look at our database and find an element with that id in there.
We will attach a then block with it where we will get an argument. In this block, we will check that our post id exists or not. If it exists, then we return a response with the status code 200 and our post as a json data otherwise we will return the response with the status code 404 and the message "Post not found" as json data in the following way:
8) Now, we just need to call this route from our client in the post.service.ts file. In the getPost() method, we returned a post. Now, we will get rid of it because it is not able to do that anymore. The reason for this is if we make an http call here, then it will be an asynchronous code, and we can't return inside of the subscription of the addPost(), so we need to return synchronously.
Instead of using that return statement in the getPost() method, we will return the observable we are getting from the angular http client so that we can subscribe to the component where we are interested in that data. We will return the observable in the following way:
We also need to explicitly add the type of data we get back in the following way:
Instead of subscribe to this in getPost() , we will subscribe this in post create component. In the ngOnInit, we would not assign this.post like this:
Instead of this, we will add a subscription which we also don't need to unsubscribe from because it is added by the angular http client therefore angular takes care of it. In the subscription of this, we know that we will eventually get our post data and we assign the values to the post in the following way:
Now, if we will go back to our app, we will see the following error:
9) We get this error because, eventually, we have the postdata but not right from the start. This is because the http request takes some time to be executed. However, the post initially is undefined, and we try to read a new value from it in the post-create.component.html file with ngModel. We will fix it by using the so-called Elvis operator. In the template, we will add a question mark after post and this will be for angular to check whether the post exists before it tries to read the title and content. It will populate the title and content filed with nothing if the post doesn't exist.
Now, if we save this and reload the page, we will not get an error.
Note: Our updating mechanism in the updatePost() method of the posts.service.ts file where we replace the old post with the id will actually not work. It will do nothing here because if we never visited our post list page, then we won't have any posts in that array, so there is nothing to update.
Now everything is working well. In the next section, we will re-organize our backend routes.