2

我正在开发一个 Angular 应用程序,ngOnChanges当组件的输入发生更改时,我会使用它来获得通知。在我的情况下,它不会被触发,因为我有一个嵌套对象数组作为组件的输入。

我有一个组件,其中我使用两个使用FormControl相同 parent 的两个子组件FormGroup。我将value第一个 formControl 的 传递给第二个子组件,但是由于在数组修改时没有发生更改检测,因此我无法在第二个子组件的 Input 中获取新值。

这是我的代码:

@Component({
    encapsulation: ViewEncapsulation.None,
    moduleId: module.id,
    selector: 'my-component',
    templateUrl: 'my-component.html',
    styleUrls: ['my-component.scss']
})
export class MyComponent {
    myForm: FormGroup;

    constructor(private fb: FormBuilder) {
        this.myForm = fb.group({
            documents: null,
            summary: null
        });
    }
}

这是模板文件:

<div class="content">
    <form class="ui form" [formGroup]="myForm">
        <my-component-child-one [form]="myForm.get('documents')"></my-component-one>

        <my-component-child-two [form]="myForm.get('summary')" [content]="myForm.get('documents').value"></my-component-two>
    </form>
</div>

对第一个子组件的表单控件所做的任何更改都不会触发ngOnChanges第二个子组件,因为它绑定的是数组引用而不是数组内容。因此,对数组的任何对象所做的任何更改或对数组本身所做的任何更改都不会更改数组引用,因此ngOnChanges()不会被调用。

一个可能的解决方案可能是使用ngDoCheck. 但它可能会产生可怕的代价,因为它被频繁调用。即使我应该使用IterableDiffersand ,它也会变得很重KeyValueDiffers

另一种解决方案可能是订阅valueChanges第一个 formControl,但我无法弄清楚为什么它似乎无法正常工作,有时它会错过一些更改......

在我的情况下,最好的解决方案是什么?

4

3 回答 3

2

我解决了Output在第一个子组件上添加一个。当数组更改时,它使用EventEmitter向父组件发出事件。然后父组件更改数组引用,以便第二个子组件检测到更改并ngOnChanges触发它。

这是代码:

@Component({
    encapsulation: ViewEncapsulation.None,
    moduleId: module.id,
    selector: 'my-component',
    templateUrl: 'my-component.html',
    styleUrls: ['my-component.scss']
})
export class MyComponent {
    myForm: FormGroup;
    documents: Array<Document>;

    constructor(private fb: FormBuilder) {
        this.myForm = fb.group({
            documents: null,
            summary: null
        });
    }

    documentsChanged = () => {
        this.documents = [].concat(this.myForm.get('documents').value);
    };
}

模板:

<div class="content">
    <form class="ui form" [formGroup]="myForm">
        <my-component-child-one [form]="myForm.get('documents')" (docs-changed)="documentsChanged()"></my-component-one>

        <my-component-child-two [form]="myForm.get('summary')" [content]="documents"></my-component-two>
    </form>
</div>

另一种解决方案可以使用andlocalStorage代替:第一个子组件将数据(如果更改)设置到本地存储;第二个子组件从中获取数据。OutputEventEmitter

于 2018-04-12T08:45:51.930 回答
0

您可以将整个传递form:FormGroup给子组件,然后无需考虑如何检测每个子组件中的更改。

StackBlitz 示例

我正在开发一个 Angular 应用程序,当组件的输入发生更改时,我会使用 ngOnChanges 来获得通知。在我的情况下,它不会被触发,因为我有一个嵌套对象数组作为组件的输入。

另外,如果你真的需要检测数组值的变化,你可以使用ngDoCheck.

NgDoCheck()检测并处理 Angular 无法或不会自行检测到的更改

于 2018-04-09T11:37:29.797 回答
0

您可以收听您的表单更改sub-component,一旦发生更改,请手动运行更改检测。

这实际上非常有效并且表现良好。

从“@angular/core”导入 {ChangeDetectorRef}

export class MySubComponent {
    @Input() form : FormGroup;
    constructor(private _cd:ChangeDetectorRef){}
    ngOnInit() {
        this.form.valueChanges.debounceTime(100).subscribe(()=>{
      //this._cd.markForCheck() only of your component is OnPush
             this._cd.detectChanges()
          })

    }
}

请注意,这debounceTime只是另一个很好的性能提升,使用它可以让我们减少更改检测调用的数量

于 2018-04-09T09:55:29.827 回答