【问题标题】:Update child component from parent in Angular从 Angular 中的父组件更新子组件
【发布时间】:2021-02-10 02:03:16
【问题描述】:

我一直在努力让它在 Angular 中工作。我有一个主机组件(父组件),它使用子组件来呈现下拉列表。列表的源是从父级传递的。因此,例如,如果父组件在源属性上传递 5 个项目,则子组件将为下拉列表呈现 5 个选项。

这是我调用子组件的部分代码:

parent.component.html

<ng-container>
   <th mat-header-cell *matHeaderCellDef>
         <app-column-header
            [id]="column.id"
            [name]="column.name"
            [source]="myObject.options"
          ></app-column-header>
   </th>
</ng-container>

parent.component.ts

export class ParentComponent  {  

@ViewChild(ChildComponent) ChildComponent;  

 // more code

  private updateChildSource() {
    this.child.updateDataSource(myObject.options);
  }
}

到目前为止一切正常。

现在,我面临的挑战是要传递的项目列表需要是动态的(myObject.options)。因此,例如,第一次让我们说我要传递 5 个项目。 Angular 采用这 5 个项目并正确渲染子组件。但是,一旦子组件已经渲染并且如果我将源更改为 2 个项目而不是来自父级的 5 个并传递新源,则子组件不会渲染新项目 (2)。

child.component.ts

export class ColumnHeaderComponent implements OnInit, OnChanges {
  @Input() id: string;
  @Input() name: string;
  @Input() source: any[];

 childField: any;

  ngOnInit(): void {
    const options = this.doStuffHere(this.source);
    this.childField= {
      id: this.id,
      options,
    };
  }

  updateDataSource(newSource: Option[]): void {
     console.log(`print call from parent. old options: 
     ${JSON.stringify(this.childField.options)} - new options: ${JSON.stringify(newSource)}`);
     this.source= newSource;
     const options = this.doStuffHere(this.source);
     this.childField= {
       id: id,
       options,
     };
  }

  ngOnChanges(changes: SimpleChanges) {
    console.log('changed');     
    for (const propName in changes) {
      const chng = changes[propName];
      const cur  = JSON.stringify(chng.currentValue);
      const prev = JSON.stringify(chng.previousValue);
      console.log(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
    }
  }
}

如前所述,子组件正在接收原始项目和新项目,甚至 ngOnChanges 方法也在捕获它并正确打印值。但由于某种原因,我还不知道子组件仍在渲染旧项目 (5) 而不是新项目 (2)。

不确定,如果我在这里遗漏了什么?或者问题足够清楚,足以说明我面临的问题。

你能指出我如何解决这个问题的正确方向吗?提前致谢。

【问题讨论】:

  • 为什么不把列表作为@Input() 传递给子组件呢? @ViewChild 使它变得不必要的复杂。当@Input() 更改时,您需要通过实现ngOnChanges 重新触发渲染,将changeDetection 更改为onPush@Input() 是一个输入属性设置器
  • 抱歉回复晚了。我正在做一些额外的更改,但您的答案是正确的。通过使用不带 @ViewChild 的 nhOnchanges 可以正常工作。我对那个答案很封闭,我认为我应该更加努力地推动自己:)。感谢您的帮助

标签: javascript angular


【解决方案1】:

正如 Marek 所说,您可以直接将父组件中的列表作为子组件的输入传递。 [list]="list" 表示法已经是反应式的。 然后,您只需使用子组件下拉列表中的列表。

注意:这里没有用,但作为@Input,你可以设置一个函数而不是一个变量。每次输入值变化都会触发。

【讨论】:

  • 我标记了这个答案,但我想感谢 sDe 和 @Marek W,为我指出正确的方向。我对那个答案很封闭:)
猜你喜欢
  • 2018-07-15
  • 2021-08-30
  • 2017-05-18
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
  • 2023-02-20
  • 1970-01-01
  • 2019-10-10
相关资源
最近更新 更多