【问题标题】:Angular Parent to Child-in-Array CommunicationAngular Parent 到 Child-in-Array 通信
【发布时间】:2019-01-09 16:44:56
【问题描述】:

我有一个由父组件控制的动态表单,带有一组子 DTO,使用 ngFor 呈现,这些子组件通过 DTO 并使用它们自己的模板。比如:

父 HTML:

<div class="row parameter-list" *ngFor='let parameter of parameters'>
  <div class="col-md-12">
    <parameter-list-item
    [parameter]="parameter"
    [types]="types"
    [events]="eventsSubject.asObservable()"
    (onDelete)="onDeleteHandler($event)">
    </parameter-list-item>
  </div>
</div>

父组件:

@Input()
parameters: Parameter[];

儿童 HTML:

<input type="text" [(ngModel)]="parameter.Name" [disabled]="readonly">
<input type="text" [(ngModel)]="parameter.Description" [disabled]="readonly">

子组件:

constructor() {
  this.readonly = true;
}

readonly: boolean;

@Input()
parameter: Parameter;

DTO:

export class Parameter {
   Name: string,
   Description: string) { }
}

当我想更改列表时,通过向父组件添加参数,我正在使用(单击)处理程序执行以下操作:

  addParameter(): void {
    console.log("ParameterListComponent.addParameter()");
    let name = "Name" + this.parameters.length;

    let parameter = new Parameter(
      name,
      "Description");

    this.parameters.unshift(parameter);
  }

基本上让 unshift 触发正确的生命周期钩子等等。

我需要知道的是,我是否可以以某种方式与新创建的子组件进行通信并将它的只读布尔值设置为 false..

【问题讨论】:

  • 您可以使用@ViewChild 来获取对子组件的引用。
  • 嗯,你会怎么声明呢?我看到的文档似乎希望您在单个子元素上使用 ViewChild,而不是数组。当您有一个子数组时,文档有点令人困惑:\
  • 嗯,找到了这个人:stackoverflow.com/questions/40165294/…,这让我更接近于理解。但是我会在哪里定义 ngAfterViewInit()?在父组件或子组件中?是否有一种简洁的方式来表达类似“if child.Name == 'Name 20' inside the hook?

标签: angular parent-child ngfor angular-components


【解决方案1】:

我想出了一个不错的解决方案;我最终只是将父级中的数组拆分为 2:

  parametersToAdd: Parameter[];

  @Input()
  parameters: Parameter[];

然后我将我的父 html 更改为如下所示:

<div class="row parameter-list" *ngFor='let parameterToAdd of parametersToAdd'>
  <div class="col-md-12">
  <parameter-list-item
    [parameter]="parameterToAdd"
    [types]="types"
    [readonly]="false"
    (onDelete)="onDeleteHandler($event)"
  ></parameter-list-item>
  </div>
</div>

<div class="row parameter-list" *ngFor='let parameter of parameters'>
  <div class="col-md-12">
    <parameter-list-item
    [parameter]="parameter"
    [types]="types"
    [readonly]="true"
    (onDelete)="onDeleteHandler($event)"
    ></parameter-list-item>
  </div>
</div>

添加点击处理程序现在看起来像:

addParameter(): void {
  console.log("ParameterListComponent.addParameter()");
  let name = "Name" + this.parameters.length;

  let parameter = new Parameter(
    name,
    "Description",
    null,
    new Array(),
    new ParameterTypeInfo(ParameterDataType.Boolean, null, null, new 
    Array(),null, null));

  this.parametersToAdd.unshift(parameter);
}

基本上有 2 个集合,它们在应用运行时呈现为相同的外观。我需要这样做是因为我们的后端 API 不允许您编辑 DTO 中的所有字段,只能编辑其中的一些。因此,对于页面加载时从后端 API 提取的现有记录,我需要子组件处于“只读”模式。相反,如果你想添加一个新的参数,那么你可以做任何你想做的事情......所以基本上现有的记录不能对它们进行很多更改,并且大多数字段需要处于只读模式,任何新记录都可以写入模式,直到您保存它们。然后它们被 POST 并且页面应该在只读集合中刷新它们。

【讨论】:

    【解决方案2】:

    许多种方式可以在父母和孩子之间交流信息。

    这里有几个:

    正如另一张海报所提到的,您可以使用@ViewChild 来获取对子组件的引用并设置它的属性。

    另一个选项(如上所示)是使用onChanges 生命周期挂钩。您可以使用它来监视任何 Input 属性的更改。因此,您可以观察 Parameter 的更改,并让孩子根据该参数更改自行设置 readonly 标志。

    另一种选择是构建一个服务来管理标志,让父设置标志值,让子标志读取它。

    对于更大或更复杂的应用程序,您可以考虑使用 NgRx 进行这种通信。 NgRx 是一个状态管理库,用于管理数据更改和通知。

    希望这会有所帮助。

    【讨论】:

    • 好评论,但鉴于复杂性,我有点不确定如何进行。基本上我需要取消移位,等待子组件的更改检测生命周期完成,然后启动发射或服务广播告诉孩子将只读翻转为假。我对更改检测的知识有点了解,所以我担心试图强制检测钩子。此外,我需要 CD 添加参数方法,而不是页面加载,因为当您获得 Parent 时,我的后端可以返回 20 多个参数。
    • 如果您可以做一个堆栈闪电战来说明您的问题(无需太多代码),它将帮助我们更好地帮助您。
    • 您需要多少代码?只是我正在使用的 2 个组件或所有的脚手架代码,如 json、app.component 等......?
    • 看来你解决了。为了将来参考,如果您尝试使用 stackblitz,您会看到它生成了所有的脚手架。您只需要添加显示您的问题所需的部分。
    猜你喜欢
    • 2018-09-22
    • 1970-01-01
    • 2016-05-10
    • 2015-01-24
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 2016-03-22
    • 2017-03-11
    相关资源
    最近更新 更多