无法通过父级组件在子级中打开表单-'无法读取属性xxx'

时间:2018-12-15 11:23:34

标签: html angular typescript angular-material

方案:我有一个公司列表,每个公司都有一组项目作为其变量之一。我将在上级组件/ html中显示公司列表,仅当单击其相应的“打开”时,子组件才会打开以显示该公司的项目列表。此列表是一个可编辑的FormArray。

我创建了这个FormArray示例作为独立的项目组件,以与示例数据进行交互并执行CRUD操作。

我现在的目标是像在 THIS stackblitz中那样,在每个公司上单击“打开”按钮时,将表单作为子组件打开。

在该示例中,构造函数中的this.setData();似乎引起了麻烦。

我通过实验发现,通过注释掉该行不会导致应用崩溃,但是当我单击公司的“打开”按钮时,当然不会加载FormArray。但是,我还发现,在子组件中写入{{company.name}}会在子组件中输出公司详细信息,因此它表明数据正在正确处理。

我就是不明白怎么了?

3 个答案:

答案 0 :(得分:1)

尝试ngDoCheck()生命周期钩子

  

一个生命周期挂钩,该挂钩为一个实例调用自定义的更改检测功能   指令,除了默认执行的检查   变更检测器。

ngDoCheck() {

  this.setData();

}

答案 1 :(得分:0)

问题出在this.setData()类构造函数中的SubForm调用中。

您从未检查过null / undefined数据。因此,最初在组件加载时,this.company是未定义的。因此,将为name变量分配undefined值。

因此,当程序尝试访问下一行中的this.company的值时,会出现错误:

setData() {
  let control = <FormArray>this.myForm.controls.data;
  control.push(this.fb.group({
    name: this.company.name,
    ...
  }));
}

解决方案:

在调用this.company之前为this.setData()添加null / undefined检查:

constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      data: this.fb.array([])
    })
    if(!isNullOrUndefined(this.company)){
      this.setData();
    }
    console.log(this.company)
}

答案 2 :(得分:0)

当我尝试StackBlitz时,要使其正常工作,需要做一些更改:

您必须通过实现@Input接口来访问ngOnInit()中的OnInit变量。

父组件.TS文件:

isOpened : boolean = false;  // one local variable of type boolean to open child compo

openInfo(company) {
    this.isOpened = !this.isOpened;
    this.openCompany = company;
    this.open=true;
}

父组件HTML代码:

<mat-card *ngFor="let data of DATA">
    {{data.name}}
    <button mat-raised-button (click)="openInfo(data)">open</button>
</mat-card>
<div *ngIf="isOpened">
  <subform [company]="openCompany"></subform>
</div>

子组件.TS代码:

导入此:

import {
  Component, OnInit, Input
} from '@angular/core';

和组件类:

export class SubForm implements OnInit {

@Input() company: any;
myForm: FormGroup;

constructor(private fb: FormBuilder) {}

ngOnInit() {
   this.myForm = this.fb.group({
      data: this.fb.array([])
   })
   console.log(this.company);
   this.setData();
  }
}

A working example