网站搜索

typescript - Angular 9:如何在组件代码中的 canDeactivate 函数中访问 HTML 中 async pipe 的结果?


在我的 Angular 9 项目中,我有这样的模板代码,用于显示来自服务的对象。并且在用户在页面上的交互时,将对象传递给组件代码。

<div *ngIf="report$ | async as report">
  ...
  <div>{{report.Title}}</div>
  <button (click)="DoSomething(report)" >Do something</button>
  ...
</div>

然而,我如何从组件代码中访问异步管道的报告对象,而该代码并不是由页面触发的。例如,在用户从当前页面导航离开时的 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
  }
}