Tamás Szabó
Tamás Szabó

Reputation: 1418

Angular5 property binding arrays with @Input

I'm trying to propagate a change from a component to one of its siblings through their parent via an EventEmitter. The change is to the status of a user in an array.

Here's my code:

child1.component.ts (source)

@Output() adminAdded = new EventEmitter<Array<AdminDetails>>();
...
setAdminStatus(index: number, status: string): void {
  this.admins[index].status = status;
  this.adminAdded.emit(this.admins);
}

parent.component.ts

onAdminAdded(adminDetails: Array<AdminDetails>): void {
  Object.assign(this.adminDetails, adminDetails]);
}

parent.component.html

<child1-component (adminAdded)="onAdminAdded($event)"></child1-component>
<child2-component [admins]="adminDetails"></child2-component>

child2.component.ts

adminMails: string[];
@Input() set admins(admins: Array<AdminDetails>) {
    if (!admins) {
        return;
    }
    adminMails = admins.filter(x => x.status === 'Active').map(x => x.email);
}

and here I'm displaying the emails of active admins. The issue is that the change only gets as far as the parent component. The breakpoint at Object.assign gets hit, but in the setter, it does not.

I assume it is because the reference to the array is the same and it doesn't recognize the change. Any ideas?

Upvotes: 0

Views: 342

Answers (1)

bugs
bugs

Reputation: 15313

You are right, Angular only detect changes when the reference object changes, but not when its content changes.

You can bypass this by moving your logic inside a DoCheck lifecycle hook, which is able to detect changes in object properties.

Edit

As discussed, If you are worried about DoCheck being called too often, creating an entirely new object and reassigning it to your input property should do the trick, as the reference would be different.

Upvotes: 2

Related Questions