Improving the UI Header to Reflect the Authentication Status in MEAN Stack
In our previous section, we successfully added the token to authenticate requests. Theoretically, our application is now made from an authentication perspective. From a user experience perspective, not so much. We can't tell whether we are authenticated or not, and we can't tell what we are allowed to do or not. So, what we have to do is, we need to hide login and signup buttons if we are logged in. We need to show a logout button that deletes the token. We also have the problem that we don't see if we are allowed to delete or edit the post. We always see these buttons, the same for the new posts. We see that even if we are not authenticated.
Now, we will work on updating the UI first. We will perform the following steps to update the UI:
1) We have the token stored in the auth service, so we can inject that service in any component where we need that token to update the UI, and one such component is the header component. In the header component, we have a couple of links that we only want to show if the user is authenticated. On the other hand, we want to add a new list item that is there to allow us to logout. That should not be a link; it should be a button and, therefore, won't have a router link.
2) Now, we will go back to our component.ts file, and here we inject the auth service where we have the token. After that, we use that auth service to get that token.
3) We should also have some listeners just as we have it for our posts because that, of course, can change. For example, if we logout and clear that token and so we want to be able to push that token information to our interested components. So, we will first go to our service.ts file, and besides storing the token there, we want to have another value or property, i.e., authStatusListener. This listener will be a new subject that will be used to push the authentication information to the interesting component. This subject will be a generic type, and for now, it will wrap a Boolean because we don't really need the token in our other component. We only need it in our interceptor.
4) We will add a new method, i.e., getAuthStatusListener. It is a private property because we only want to return the observable part of that listener. So, we will return AuthStatusListener as observable so that we can't emit new values from other components. We only want to be able to emit from within the service, but also to listen from other parts of the app, of course.
5) Now the other parts can call this method to get the listener. We want to emit a new value in our login() method after we got the token. We will use the listener and call the next() method. In this method, we pass the value true like this:
6) We got a way of informing everyone who is interested in the user being authenticated, and now we go back to our header component, where we inject the auth service. Here, we will now implement OnInit, which will be imported from @angular/core. We will implement it by adding the ngOnInit method.
7) Now, in this method, we will set up our subscription to that AuthStatusListener. We know that the subscriptions for observables or subjects managed by us also need to be managed, so we should unsubscribe if the component gets destroyed. So, we will implement onDestroy too, which forces us to add the ngOnDestroy method too.
8) We will add new private property, i.e., authListenerSubs and that will be of type subscription. After that in the ngOnInit() method, we will set this property to the subscription we setup from authService's getAuthStatusListener() method and then subscribe like as:
9) In the ngOnDestroy() method, we will take that subscription and unsubscribe that.
10) In the subscription method, we will get the result, and we do something here. We will set another property to store the subscription result. This property will initially be false.
11) So, now we can push that information to components and use them in the components like this header component. Now, we will use that userIsAuthenticated property in the header.component.html file. For the new post list item, we will add ngIf and set it to userIsAuthenticated. So, if the user is authenticated only, then we will see this.
In the same way, we will add this for our logout button. For login and signup button, we will set *ngIf equals to "!userIsAuthenticated" like this:
Now, we save all the files and go back to our angular app. We will see only login and signup buttons, and after logging in successfully, we will see the new post and logout buttons.
Everything is working well, and the thing which we need to do is, we need to improve the UI messages to reflect the authentication status. That is something which we will do in the next section.