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

时间:2019-01-31 04:15:17

标签: angular ngfor angular2-changedetection

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

当更新单个用户模型上的属性时,子组件不会反映此更改。我了解为什么会这样。我了解只有在列表中的引用发生更改时,更改检测才会启动。但是,我不知道该如何解决该问题。我尝试将用户模型数组实现为可观察的并使用异步管道,该管道可用于显示数据,但不能在进行更改时使用。

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

Property.save

父组件在模板中具有以下内容:

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>

和子组件模板:

export class ChildComponent {
    @Input() user: UserModel;

    firstname: string;
    lastname: string;
    selected: boolean;

    ngOnChanges() {
        if (this.user) {
            this.firstname = this.user.firstname;
            this.lastname = this.user.lastname;
            this.selected = this.user.selected;
        }
    }
 }

2 个答案:

答案 0 :(得分:1)

您只需坚持基于不变性的方法,并使用更新的属性创建浅表副本,而不用对源对象进行突变。

在您的用例中,您可以通过更改全选的实现来实现:

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

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

答案 1 :(得分:-1)

下面的代码部分是无法理解的。为什么在表行中传递输入?

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

和在输入的变化可以通过在子组件SimpleChanges捕获。您应该尝试这样的事情。

  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;
        }
    }