typescript - Angular 9: コンポーネントコードの canDeactivate 関数から HTML の async パイプの結果にアクセスする方法は?
私のAngular 9プロジェクトでは、サービスからオブジェクトを表示するためのテンプレートコードがあり、ページ上でのユーザーの操作に応じてそのオブジェクトをコンポーネントのコードに渡します。
<div *ngIf="report$ | async as report">
...
<div>{{report.Title}}</div>
<button (click)="DoSomething(report)" >Do something</button>
...
</div>
しかし、ページからトリガーされないコンポーネントコードから、async パイプのレポートオブジェクトにどのようにアクセスできますか。例えば、ユーザーが現在のページから移動するときの CanDeactivate 関数の中でです。
export class ReportComponent implements OnInit {
report$: Observable<Report>;
constructor(
private route: ActivatedRoute,
private router: Router,
private location: Location,
private reportService: ReportService
) { }
ngOnInit() {
this.report$ = this.route.paramMap.pipe(
switchMap((params: ParamMap) => this.reportService.getReport(Number(params.get('id')))
)
);
}
DoSomething(report: Report) {
...
}
canDeactivate(): Observable<boolean> | boolean {
if isReportChanged("How to access the report object from here?")
return false;
return true;
}
}
回答 #1
これは以下のように達成できます(参考までに)
TSファイル
import { Component , OnInit} from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
})
export class AppComponent implements OnInit {
reports :any[] = [
{Title:"Report 1"},
{Title:"Report 2"},
{Title:"Report 3"},
{Title:"Report 4"},
{Title:"Report 5"}
]
ngOnInit(){
this.reports.forEach(s=>Object.assign(s,{IsTouched:false}));
//initialize a new field to mark as touched.
}
DoSomething(report) {
this.reports.find(s=>s.Title == report.Title).IsTouched = true;
}
OnDeactive()
{
console.log(JSON.stringify(this.reports.filter(s=>s.IsTouched)))
}
}
HTML
<div *ngFor="let report of reports">
<div>{{report.Title}} - {{report.IsTouched}}</div>
<button (click)="DoSomething(report)" >Do something</button>
</div>
<br>
<button (click)="OnDeactive()">Back Button Simulate</button>
ここでは、コンポーネントのバックボタンイベントハンドラー内で OnDeactive() を呼び出すことができます。
回答 #2
あなたのHTMLでは、このようなものを提案します:
<ng-container *ngIf="report$ | async as report">
{{ setReportData(report) }}
</ng-container>
これはデータのストリームで実行する関数を呼び出すべきです
そして次に、あなたのTSでその関数を定義し、それが受け取るデータに対して何をするかを決めます。例のように行うと、バックエンドのレポート変数が設定され、それを他の関数呼び出しで使用することができます:
report: Report;
...
setReportData(report: Report): void{
if(this.report === null || this.report === undefined) {
this.report = report
}
}
