Issue
Right, so i have a header component (navbar) which contains the following template:
<ng-template [ngIf] = "authService.isAuthenticated()">
<li>
<a routerLink="Landing" class="navbar-brand" (click)="Logout()"><span class="xvrfont">Logout</span><i class="fa fa-sign-in" aria-hidden="true"></i></a>
</li>
<li>
<a routerLink="Profile" class="navbar-brand"><span class="xvrfont">{{authService.getUsername()}}</span><i class="fa fa-user-circle" aria-hidden="true"></i></a>
</li>
</ng-template>
This part of the nav should be visible when the user is authenticated. to find out it checks via authService.
To check if a user is authenticated, the following code is ran on every route change:
checkAuthenticated(){
if (localStorage.getItem('token') != null){ this.authenticated = true; }
else { this.authenticated = false; }
console.log(this.authenticated); // for Debugging.
}
The NgIf statement calls this method:
public isAuthenticated(){
return this.authenticated;
}
According to the logs, 'authenticated' is changing between true and false correctly, but the Ngif isn't responding to the changes somehow.
the header component.ts looks like this:
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import {AuthService} from "../auth/auth.service";
@Component({
selector: 'app-header',
providers: [AuthService],
templateUrl: './header.component.html',
styleUrls: ['./header.component.css'],
encapsulation: ViewEncapsulation.None
})
export class HeaderComponent implements OnInit {
constructor(private authService: AuthService) { }
ngOnInit() {
}
Logout(){
this.authService.Logout();
}
}
Any help would be appreciated. Thanks.
Edit:
auth.service.ts:
import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Router} from "@angular/router";
import 'rxjs/add/operator/map';
@Injectable()
export class AuthService {
public apiroot = 'http://localhost:3100/';
public loginResponseMessage = '';
public registerResponseMessage = '';
public authenticated = false;
public constructor(private http: HttpClient,
private router: Router) {
}
SignUp(username: string, password: string) {
const User = JSON.stringify({username: username, password: password});
let response: any;
this.http.post(this.apiroot + 'register', User, {headers: new HttpHeaders()
.set('content-type', 'application/json; charset=utf-8')})
.subscribe(res => {
response = res;
this.registerResponseMessage = response.message;
console.log(this.registerResponseMessage);
});
}
Login(username: string, password: string) {
const User = JSON.stringify({username: username, password: password});
let response: any;
this.http.post(this.apiroot + 'authenticate', User, {headers: new HttpHeaders()
.set('content-type', 'application/json; charset=utf-8')})
.subscribe(res => {
response = res;
this.loginResponseMessage = response.message;
if (response.token) {
localStorage.setItem('token', response.token);
this.authenticated = true;
localStorage.setItem('user', response.username);
this.router.navigate(['/']);
}
else{ /* Do Nothing */ }
});
}
Logout(): void{
this.authenticated = false;
localStorage.removeItem('token');
console.log(this.isAuthenticated());
this.router.navigate(['/Landing']);
}
isAuthenticated(){
return this.authenticated;
}
checkAuthenticated(){
if (localStorage.getItem('token') != null){ this.authenticated = true; }
else { this.authenticated = false; }
console.log(this.authenticated); // for Debugging.
}
getUsername(){
var result = localStorage.getItem('user');
return result;
}
}
Solution
The problem is that you are providing the service at component level, that means, that all your components, that have the service added to providers array in component will have their own instance of service, so this is not a shared service at all. You want to have a singleton service, so only set the service in your providers array in your ngModule.
Also like mentioned by others, calling methods in template is a really bad idea, this method is called on each change detection, which is often, so it really hurts the performance of the app.
You could use Observables like suggested, or then just have a shared variable in your service. In the long run I'd suggest Observables, but depending on case just a shared variable is alright. Here's a sample for both: Passing data into "router-outlet" child components (angular 2)
Answered By - AT82
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.