そうです、次のテンプレートを含むヘッダーコンポーネント(navbar)があります。
<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>
ユーザーが認証されると、ナビゲーションのこの部分が表示されるはずです。 authServiceを介してチェックすることを確認します。
ユーザーが認証されているかどうかを確認するために、ルートが変更されるたびに次のコードが実行されます。
checkAuthenticated(){
if (localStorage.getItem('token') != null){ this.authenticated = true; }
else { this.authenticated = false; }
console.log(this.authenticated); // for Debugging.
}
NgIfステートメントはこのメソッドを呼び出します。
public isAuthenticated(){
return this.authenticated;
}
ログによると、 'authenticated' isはtrueとfalseの間で正しく変化していますが、Ngifは何とかしてその変化に応答していません。
ヘッダーcomponent.tsは次のようになります。
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();
}
}
任意の助けをいただければ幸いです。ありがとう。
編集:
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;
}
}
問題は、コンポーネントレベルでサービスを提供していることです。つまり、コンポーネントのproviders
配列に追加されたサービスを持つすべてのコンポーネントには、独自のインスタンスがあります。 サービスなので、これは共有サービスではありません。シングルトンサービスが必要なため、onlyngModule.
のproviders
配列にサービスを設定します。
また、他の人が述べたように、テンプレートでメソッドを呼び出すことは非常に悪い考えです。このメソッドは変更検出ごとに呼び出されます。これは頻繁に行われるため、アプリのパフォーマンスを本当に損ないます。
提案されているようなObservablesを使用するか、サービスに共有変数を設定するだけです。長期的にはObservablesをお勧めしますが、場合によっては共有変数だけで問題ありません。両方のサンプルを次に示します。 「ルーターアウトレット」の子コンポーネントにデータを渡す(角度2)
良い方法は、リアクティブコーディングを通じてObservableとデータを共有することです。
サービスで、BehaviorSubjectとそのObservableを作成します。
private _isAuthenticatedSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public isAuthenticatedObs: Observable<boolean> = _isAuthenticatedSubject.asObservable();
値を更新するたびに、件名でnext
を実行します。
_isAuthenticatedSubject.next(true); // authenticated
_isAuthenticatedSubject.next(false); // no more
コンポーネント側では、オブザーバブルをサブスクライブして、サブジェクトの変更ごとに値をローカルに設定します。
this.authService.isAuthenticatedObs.subscribe(isAuth => this.isAuth = isAuth);
または、非同期パイプを使用してテンプレートに値を表示します。
<ng-template *ngIf = "authService.isAuthenticatedObs | async">
テンプレートは
<ng-template *ngIf = "authService.isAuthenticated()">