0

I checked following two questions, but there aren't any useful answers:

  1. Detect change in object of input array
  2. Detect changes in component input when it is a object

I have a scenario where I need to pass a different type of data to a child component using @Input(). By different type of data, I meant I've a string, a number, a Boolean, an object and an array.

Parent HTML:

<app-child
  [stringData]="stringData"
  [numberData]="numberData"
  [booleanData]="booleanData"
  [objectData]="objectData"
  [arrayData]="arrayData"
></app-child>

<button (click)="changeData()">Change data</button>

When I click on the button, the changeData() method is called. Here I'm modifying the data as follows:

Parent TypeScript code:

stringData: string = 'testing something';
numberData: number = 0;
booleanData: boolean = false;
objectData: any = {
  student: { name: 'tanzeel', batch: 2016 },
};
arrayData: any[] = ['banana'];

constructor() {}

changeData() {
  this.stringData = 'rolex watch';
  this.numberData = 100;
  this.booleanData = true;
  this.objectData.student.name = 'tajknzeel';
  this.arrayData.push('apple');
}

I'm receiving this data in the Child component as @Input properties.

Child TypeScript code:

@Input() stringData: any;
@Input() numberData: any;
@Input() booleanData: any;
@Input() objectData: any;
@Input() arrayData: any;

ngOnChanges(changes: SimpleChanges) {
    console.log(changes);
}

The problem is that objectData and arrayData changes are going undetected.

Console output:

{
    "stringData": {
        "previousValue": "testing something",
        "currentValue": "rolex watch",
        "firstChange": false
    },
    "numberData": {
        "previousValue": 0,
        "currentValue": 100,
        "firstChange": false
    },
    "booleanData": {
        "previousValue": false,
        "currentValue": true,
        "firstChange": false
    }
}

What is the mistake in my code?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tanzeel
  • 4,174
  • 13
  • 57
  • 110
  • 1
    Mutating an object or array doesn't kick off the change detection mechanism. You have to reassign the values. – derstauner Aug 05 '23 at 11:38

1 Answers1

1

The change detector only recognizes changes to the object reference, not its value.

For strings, numbers, and Booleans, changing the simple value actually does change the instance that the variable refers to.

For objects and arrays, you must change the instance of the object or array to trigger change detection. Changing an object property or the contents of the array does not trigger a change detection.

So, to make this work, change

this.objectData.student.name = 'tajknzeel';
this.arrayData.push('apple');

to

this.objectData = Object.assign(
   {},
   this.objectData,
   {
       student: Object.assign(
         {}, this.objectData, {name: 'tajknzeel'}
       )
   }
);
this.arrayData = [...this.arrayData, 'apple'];
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67
  • I also noticed that I can trigger change for Object by doing this: ``` this.objectData = { student: { name: 'tajknzeel', batch: 2018766 }, }; ``` – Tanzeel Aug 05 '23 at 16:55