1

I have a list of an array(dataSource) on which I am performing Add and Delete operations. I have passed an array(dataSource) in the child component and added *ngFor loop in the child. Array I have passed as getter setter for detect @Input change.

This is my AppComponent :

<div>
    <vertital-tabs
          [config]="config"
          [dataSource]="dataSource"    <-- Array changes I want to detect in Child
          [(selectedItem)]="selectedItem">
    </vertital-tabs>

    <div style="background-color: yellow;margin: 10px">
        {{ selectedItem | json }}
     </div>
</div>

In ChildComponent (vertical-tabs) :

get dataSource(): any {
    return this._dataSource;
}

@Input() set dataSource(value: any) {
    this._dataSource = value;
    // Not called this on Add New button even if Input Datasource is changed.
    // I want this to be called on Add New Item button click....
    debugger;
}

Problem is that when I am adding a new item on the array, it is not calling the setter @Input change method. When I am deleting an item it is working fine and call @Input change.

Note: I have lot of properties as an Input in real scenario so I don't want to use ngOnChanges()

Here is an example I have created: https://stackblitz.com/edit/angular-vertical-tabs-component-split-yzynef

1 Answer 1

6

Angular only checks whether the reference has changed - if it has not changed since the last check the setter will not be called.

In app.component.ts:

let nextItem = this.dataSource.length;
this.dataSource.push({
  id: nextItem.toString(),
  text: 'item ' + nextItem.toString(),
  icon: 'settings',
});

Here you add something to your array instead of creating a new array and assigning it to dataSource.

In vertical-tabs.ts:

onDelete(item, index) {
  this.dataSource = this.dataSource.filter((x) => x !== item);
}

Here you create a new array and assign it to dataSource.

That's why deletion works as you expect, but adding doesn't. Copying the array and assigning it to dataSource should solve your problem:

let nextItem = this.dataSource.length;
this.dataSource = [
  ...dataSource,
  {
    id: nextItem.toString(),
    text: 'item ' + nextItem.toString(),
    icon: 'settings',
  }
];
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the explanation @majusebetter. It is working as expected. But in the real scenario, my dataSource is FormArray. So, How can I assign a new value for that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.