【问题标题】:Unable to share Observable Subject service between grandchildren components in Angular 5无法在 Angular 5 中的孙子组件之间共享 Observable Subject 服务
【发布时间】:2018-12-07 12:06:00
【问题描述】:

我有一个应用程序,我正在使用角度 cdk 步进器,并且我试图在两个子步进组件中的一个公共孙组件之间共享数据。

第一个孩子传递数据来填充孙子,但问题似乎是步进器同时初始化两个组件,并且由于第一个孩子必须进行服务调用来填充孙子,所以第二个孩子的child 用不完整的数据初始化。

parent.component.html:

<app-custom-stepper>
<cdk-step [stepControl]="frmStep1" #step1="cdkStep">
<ng-template cdkStepLabel>Step1</ng-template>
    <form #frmStep1="ngForm">
        <child1 [myData]="myData"></child1>
    </form>
    <button cdkStepperPrevious>Prev</button>
    <button cdkStepperNext>Next</button>
</cdk-step>
<cdk-step cdkStep #step2="cdkStep">
    <form #frmStep2="ngForm">
        <child2></child>
    </form>
    <button cdkStepperPrevious>Prev</button>
    <button cdkStepperNext>Next</button>
</cdk-step>

parent.service.ts

export class ParentService {
  myData:Subject<any> = new Subject<any>();

  setMyData(data: any) {
     this.myData.next(data);
  }

  getMyData(): Observable<any> {
     return this.myData.asObservable();
  }
}

child1.component.html:

<sharedGrandchild [myData]="myData"></sharedGrandchild>

child2.component.html

<sharedGrandchild></sharedGrandchild>

grandchild.component.ts:

@Input() myData:MyData;
ngOnInit() {
  if(this.myData) {
    //call service that populates data, this only happens on the page
    //step of the stepper
    this.parentService.setMyData(response);
  } else {
    this.parentService.getMyData()
      .subscribe( myData => {
        this.myData = myData 
      }
   };

我尝试过的事情:

使用 BehaviorSubjects 和 Subjects(如上面的代码) 使用开关延迟第二个子组件的初始化 尝试使用其他生命周期钩子来初始化第二个子组件的订阅。

问题在于时间,第一个孩子通过孙子触发的请求需要很长时间才能返回,因此第二个孩子中的孙子订阅了一个仅部分存在的对象。这似乎永远不会更新。所以页面上的第一个孩子加载很好,因为它直接点击服务,步进器第二页上的第二个孩子由于同时被初始化而数据不完整。

【问题讨论】:

    标签: angular reactjs observable subject


    【解决方案1】:

    您应该按照这些步骤来确保异步共享数据-

    1.使用BehaviorSubject存储上次设置的值。

       myData:Subject<any> = new BehaviorSubject<any>(null);
    

    2.在函数ngAfterViewInit而不是ngOnInit中读取和设置数据

    @Input() myData:MyData;
    ngAfterViewInit() {
      if(this.myData) {
        //call service that populates data, this only happens on the page
        //step of the stepper
        this.parentService.setMyData(response);
      } else {
        this.parentService.getMyData()
          .subscribe( myData => {
            this.myData = myData 
          }
       };
    

    3.确保在公共模块或主模块或根模块中提供ParentService

    【讨论】:

      猜你喜欢
      • 2018-09-27
      • 1970-01-01
      • 1970-01-01
      • 2017-10-16
      • 2020-06-18
      • 2017-10-31
      • 2019-07-25
      相关资源
      最近更新 更多