Angular detectChanges 不适用于子组件

Lpp*_*Edd 11 angular-material angular

编辑:我只是不知道为什么,但更改检测在层次结构中的第一个孩子处停止。如果我手动调用更深一层(在 中sch-job-detail)的更改检测,则更新值。

我已经建立了一个MatTable可扩展的行。
“可扩展”行部分如下:

<!-- Hidden cell -->
<ng-container matColumnDef="expandedDetail">
    <td mat-cell *matCellDef="let jobModel" [attr.colspan]="displayedColumns.length">
        <div
            class="detail-cell"
            *ngIf="jobModel.isExpanded"
            [@detailExpand]
        >
            <sch-job-detail
                [jobModel]="jobModel"
                ...
            ></sch-job-detail>
        </div>
    </td>
</ng-container>
Run Code Online (Sandbox Code Playgroud)

如您所见,该表拥有一个JobModel(s)数组,每一行都接收自己的JobModel实例。
JobModel是 a 的包装器FormGroup,它也是一个简单接口对象的“换位” Job

sch-job-detail 有其他子组件,例如:

<!-- Toolbar -->
<div class="col">
    <sch-job-row-toolbar
        [isNew]="jobModel.isNew"
        [isEdit]="jobModel.isEdit"
        [isError]="jobModel.isError"
        [isValid]="jobModel.isValid"
        ...
    ></sch-job-row-toolbar>
</div>
Run Code Online (Sandbox Code Playgroud)

在扩张行我有一个按钮,它可以让用户输入一个新的cron表达式,而随后的Cron表达式被添加到FormGroupFormControl

里面TableComponent

public addCronExpression(jobModel: JobModel): void {
    this.matDialog
        .open<CronDialogSmartComponent, any, string>(CronDialogSmartComponent)
        .afterClosed()
        .pipe(filter<string>(c => !!c))
        .subscribe(c => {
                jobModel.addCronExpression(c)
                this.changeDetector.detectChanges()
            }
        )
}
Run Code Online (Sandbox Code Playgroud)

JobModel#addCronExpression

public addCronExpression(cronExpression: string): void {
    const cronExpressions = this.formGroup.controls.cronExpressions
    cronExpressions.setValue([...cronExpressions.value, cronExpression])
}
Run Code Online (Sandbox Code Playgroud)

如您所见,由于我没有更改JobModel实例,所以我运行detectChanges以更新TableComponent和它的子项,sch-job-row-toolbar包括我想!

事情sch-job-row-toolbar似乎没有重新计算它的绑定(ngOnChanges 没有运行)。

所以这些值:

[isNew]="jobModel.isNew"
[isEdit]="jobModel.isEdit"
[isError]="jobModel.isError"
[isValid]="jobModel.isValid"
Run Code Online (Sandbox Code Playgroud)

没有改变。
我们可以JobModel#isEdit举个例子:

get isEdit(): boolean {
    return this.formGroup.dirty || Job.isEdit(this.job.status)
}
Run Code Online (Sandbox Code Playgroud)

我不知道发生了什么,但我知道如果我按下按钮或在其他地方切换选项卡,则会sch-job-row-toolbar收到更新的值。

所有组件都使用onPush策略。

说明性 GIF: 在此处输入图片说明

而且,有趣的是,当我从第一个选项卡做同样的事情时,它起作用了! 在此处输入图片说明

尝试使用Default更改检测策略,但结果相同。

小智 2

为什么不使用@Inputand@Output来检测从父组件到子组件的更改?我想建议您使用@Input (parent => child)和 使用@Output (child=> parent) 而不是detectChanges()

  • 我建议不要在回答中使用反问句。他们可能会被误解为根本不是答案。您正在尝试回答本页顶部的问题,不是吗?否则请删除此帖子。 (3认同)