TheAnonymousModeIT
TheAnonymousModeIT

Reputation: 913

Angular 2 change detection - push data into array

I would like to pass an array of data to a child component. Depending on events in the child component the data may change:

HTML (parent):

<child-component [data]="array" (event)="updateArray()"/>

TypeScript (parent).

updateArray() {
  ...
  this.array.push(more data)
  ...
}

The new data in the array should be re-rendered in the child component. But Angular does not regonize the changes.

I found a solution: https://chrislo.ca/angular-2345-change-detection-on-data-bound-array-pushunshift-popshift-or-splice/

pushAndUpdate(x) {
  this.myArray = [...this.myArray, x];
}

It creates a new array.

My question is: is this the best way or is there something better?

Upvotes: 3

Views: 4790

Answers (2)

Eliseo
Eliseo

Reputation: 57919

if you put ChangeDetectionStrategy.OnPush in children, you need use this.myArray = [...this.myArray, x]; -change the array- else you has no make any change.

the stackblitz

//hello, no change ChangeDetectionStrategy
@Component({
  selector: 'hello',
  template: `Hello <div *ngFor="let item of array">{{item}}</div>`,
  styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent  {
  @Input() array: any[];
}

//hello2, ChangeDetectionStrategy
@Component({
  selector: 'hello2',
  template: `Hello2 <div *ngFor="let item of array">{{item}}</div>`,
  styles: [`h1 { font-family: Lato; }`],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class HelloComponent2  {
  @Input() array: any[];
}

main.component:

<hello  [array]="array"></hello>
<hr/>
<hello2 [array]="array"></hello2>

<button (click)="click()">push</button>
<button (click)="click2()">CopyArray</button>


array=[1,2,3,4]
  click2(){
    this.array=[...this.array,1]
  }
  click(){
    this.array.push(1)
  }

Update there another way

In main component:

  constructor(private cdr:ChangeDetectorRef){}
  click3(){
    this.array.push(1)
    this.cdr.detectChanges()
  }

Upvotes: 3

parth jansari
parth jansari

Reputation: 178

you can use subject/observables with markForCheck() in your child-component


@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {
  @Input() data: Observable<any>;
  foods: string[] = [];

  constructor(private cd: ChangeDetectorRef) {}

  ngOnInit() {
    this.data.subscribe(food => {
      this.foods = [...this.foods, ...food];
      this.cd.markForCheck();
    });
  }
}

and in your function, you can use a subject like this

subject = new Subject();
pushAndUpdate(x) {
  this.myArray.push(x);
  this.myArray = this.subject.next(this.myArray);
}

for more details on the subject check out this

Upvotes: -2

Related Questions