Angular 更改检测不适用于NgFor中使用的复杂对象

Angular 更改检测不适用于NgFor中使用的复杂对象,angular,ngfor,angular2-changedetection,Angular,Ngfor,Angular2 Changedetection,我用的是angular 7。我有一个父组件,它从api获取用户模型列表。当“get”成功时,它与ngFor循环一起使用,使用@input将每个用户注入到子组件中,该@input将显示用户列表 更新单用户模型上的特性时,子组件不会反映此更改。我明白为什么会这样。我理解,只有当列表中的引用发生更改时,更改检测才会生效。然而,我不知道如何避开这个问题。我已经尝试将用户模型数组实现为可观察的,并使用异步管道,它可以显示数据,但在进行更改时不起作用 在我的特定示例中,我的用户模型上有一个“selected

我用的是angular 7。我有一个父组件,它从api获取用户模型列表。当“get”成功时,它与ngFor循环一起使用,使用@input将每个用户注入到子组件中,该@input将显示用户列表

更新单用户模型上的特性时,子组件不会反映此更改。我明白为什么会这样。我理解,只有当列表中的引用发生更改时,更改检测才会生效。然而,我不知道如何避开这个问题。我已经尝试将用户模型数组实现为可观察的,并使用异步管道,它可以显示数据,但在进行更改时不起作用

在我的特定示例中,我的用户模型上有一个“selected”属性,我的父组件上有一个“select all”按钮,我想用它来更改数组中所有用户的“selected”属性,然后在UI上显示它。这是我的代码的一个非常简单的版本

export class ParentComponent {
users: UserModel[];

    ngOnInit() {
       this.userService.getUsers().subscribe(users => {
        this.users = users;
       });
    }

    onSelectAll() {
        for (let user of this.users) {
            user.selected  = true;
        }
    }
}
父组件在模板中具有以下内容:

<tr users-item [index]="i + 1" [user]="user" *ngFor="let user of users; let i = index"></tr>
和子组件模板:

<td><input type="checkbox" [checked]="selected"></td>
<td>{{ fullname }}</td>
<td>{{ lastname }}</td>

{{fullname}}
{{lastname}}

以下部分代码不可理解。为什么要在表行中传递输入

<tr users-item [index]="i + 1" [user]="user" *ngFor="let user of users; let i = index"></tr>

您可以简单地坚持基于不变性的方法,创建具有更新属性的浅拷贝,而不是改变源对象

在您的用例中,您可以通过更改“全选”的实现来实现这一点:

onSelectAll() {
    this.users = this.users.map(user => this.mergeUser(user, {selected: true}));
}

private mergeUser(source: UserModel, updated: Partial<UserModel>): UserModel{
   return {...source, ...updated};
}
onSelectAll(){
this.users=this.users.map(user=>this.mergeUser(user,{selected:true}));
}
私有合并用户(来源:UserModel,更新:Partial):UserModel{
返回{…源,…已更新};
}

尝试将
更改为
,或者在链接上复制您的问题并共享链接,因为一旦呈现所有内容,它将呈现为行和列。同样,使用SimpleChanges也不会有任何区别,因为ngOnChanges只在更改检测开始时注册。只有当参考资料发生变化时,变化检测才会生效。谢谢你,先生。它不仅很有魅力,还教会了我一些关于角度/字体的知识。
  ngOnChanges(changes: SimpleChanges) {
        if (changes.user && changes.user.currentValue) {
            this.firstname = changes.user.currentValue.firstname;
            this.lastname = changes.user.currentValue.lastname;
            this.selected = changes.user.currentValue.selected;
        }
    }
onSelectAll() {
    this.users = this.users.map(user => this.mergeUser(user, {selected: true}));
}

private mergeUser(source: UserModel, updated: Partial<UserModel>): UserModel{
   return {...source, ...updated};
}