私のページ構造は:
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
ページ全体を更新せずにapp-header
コンポーネントを更新/更新するにはどうすればよいですか?
ユーザーが正常にログインしたら、ヘッダーの「サインイン」リンクを非表示にしたいと思います。ヘッダーはすべてのコンポーネント/ルートで共通です。
アプリ全体でさまざまなコンポーネント間の通信にBehaviorSubject
を使用できます。サブスクライブして変更を送信できるBehaviorSubject
を含むデータ共有サービスを定義できます。
データ共有サービスを定義する
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataSharingService {
public isUserLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
}
DataSharingService
プロバイダーエントリにAppModule
を追加します。
次に、DataSharingService
を<app-header>
と、サインイン操作を実行するコンポーネントにインポートします。 <app-header>
でisUserLoggedIn
件名の変更をサブスクライブします。
import { DataSharingService } from './data-sharing.service';
export class AppHeaderComponent {
// Define a variable to use for showing/hiding the Login button
isUserLoggedIn: boolean;
constructor(private dataSharingService: DataSharingService) {
// Subscribe here, this will automatically update
// "isUserLoggedIn" whenever a change to the subject is made.
this.dataSharingService.isUserLoggedIn.subscribe( value => {
this.isUserLoggedIn = value;
});
}
}
<app-header>
htmlテンプレートに、*ngIf
条件を追加する必要があります。例:
<button *ngIf="!isUserLoggedIn">Login</button>
<button *ngIf="isUserLoggedIn">Sign Out</button>
最後に、ユーザーがログインしたら、イベントを発行するだけです。例:
someMethodThatPerformsUserLogin() {
// Some code
// .....
// After the user has logged in, emit the behavior subject changes.
this.dataSharingService.isUserLoggedIn.next(true);
}
多くの解決策の1つは、ヘッダーに表示するデータを保持する@Injectable()
クラスを作成することです。他のコンポーネントもこのクラスにアクセスしてこのデータを変更し、ヘッダーを効果的に変更できます。
もう1つのオプションは、@Input()
変数と@Output()
EventEmittersを設定して、ヘッダーデータを変更することです。
編集要求通りの例:
@Injectable()
export class HeaderService {
private _data;
set data(value) {
this._data = value;
}
get data() {
return this._data;
}
}
他のコンポーネント:
constructor(private headerService: HeaderService) {}
// Somewhere
this.headerService.data = 'abc';
ヘッダーコンポーネント:
let headerData;
constructor(private headerService: HeaderService) {
this.headerData = this.headerService.data;
}
私は実際にこれを試していません。 get/setが機能しない場合は、Subject();を使用するように変更できます。
// Simple Subject() example:
let subject = new Subject();
this.subject.subscribe(response => {
console.log(response); // Logs 'hello'
});
this.subject.next('hello');
コンポーネントを更新するには
@Injectable()
export class LoginService{
private isUserLoggedIn: boolean = false;
public setLoggedInUser(flag) { // you need set header flag true false from other components on basis of your requirements, header component will be visible as per this flag then
this.isUserLoggedIn= flag;
}
public getUserLoggedIn(): boolean {
return this.isUserLoggedIn;
}
Login Component ts
Login Component{
constructor(public service: LoginService){}
public login(){
service.setLoggedInUser(true);
}
}
Inside Header component
Header Component ts
HeaderComponent {
constructor(public service: LoginService){}
public getUserLoggedIn(): boolean { return this.service.getUserLoggedIn()}
}
template of header component: Check for user sign in here
<button *ngIf="getUserLoggedIn()">Sign Out</button>
<button *ngIf="!getUserLoggedIn()">Sign In</button>
NgIfを使用してshow hideのような多くのアプローチを使用できます
App Component ts
AppComponent {
public showHeader: boolean = true;
}
App Component html
<div *ngIf='showHeader'> // you show hide on basis of this ngIf and header component always get visible with it's lifecycle hook ngOnInit() called all the time when it get visible
<app-header></app-header>
</div>
<router-outlet></router-outlet>
<app-footer></app-footer>
サービスも利用できます
@Injectable()
export class AppService {
private showHeader: boolean = false;
public setHeader(flag) { // you need set header flag true false from other components on basis of your requirements, header component will be visible as per this flag then
this.showHeader = flag;
}
public getHeader(): boolean {
return this.showHeader;
}
}
App Component.ts
AppComponent {
constructor(public service: AppService){}
}
App Component.html
<div *ngIf='service.showHeader'> // you show hide on basis of this ngIf and header component always get visible with it's lifecycle hook ngOnInit() called all the time when it get visible
<app-header></app-header>
</div>
<router-outlet></router-outlet>
<app-footer></app-footer>
Angularは、変数の変更を検出すると、コンポーネントを自動的に更新します。
したがって、「更新」するために必要なのは、ヘッダーに新しいデータへの参照があることを確認することだけです。これは、header.component.ts
または@Input
変数...
例...
main.html
<app-header [header-data]="headerData"></app-header>
main.component.ts
public headerData:int = 0;
ngOnInit(){
setInterval(()=>{this.headerData++;}, 250);
}
header.html
<p>{{data}}</p>
header.ts
@Input('header-data') data;
上記の例では、ヘッダーは250msごとに新しいデータを受け取り、コンポーネントを更新します。
Angularのライフサイクルフックの詳細については、以下を参照してください。 https://angular.io/guide/lifecycle-hooks