Hama Bohel
Hama Bohel

Reputation: 105

Array made by array.push() has elements but couldn't use angular

I have 2 Array<object>. One of them has initial elements and another one has its elements added by array.push() in ngOnInit. In the end, both have the elements in output but html doesn't render the elements which were pushed with .push

//the result of array that made by array.push
> [] 
 > 0: {id: '1', title: 'title 1'}
 > 1: {id: '2', title: 'title 2'}
 > 2: {id: '3', title: 'title 3'}
   length: 3
 > __proto__: Array(0)


//initialize array
> (3) [{…}, {…}, {…}] 
 > 0: {id: '1', title: 'title 1'}
 > 1: {id: '2', title: 'title 2'}
 > 2: {id: '3', title: 'title 3'}
   length: 3
 > __proto__: Array(0)

the code

newObj;
error;

myObjects: Array<object> = [];

itsObjects: Array<object> = [
  {
    id: '1',
    title: 'title 1'
  },
  {
    id: '2',
    title: 'title 2'
  },
  {
    id: '3',
    title: 'title 3'
  }
];

ngOnInit() {
  this.subscription = this.mys.myService().subscribe(
    res => {
      this.newObj = res,
      this.myObjects.push(
          {
            id: element.id,
            title: element.title
          }
        )
    },
    error => this.error = error,
  )
}

Solved

The main notice was this.myObjects = this.tmpObj after forEach that collects all elements for pass to out of ngOnInit scope, I edited my code to:

servicOutput; //get data
tmpObj: Array<object> = []; //manage data as temp;
myObjects: Array<object> = []; //for collect all elements to html
error;

ngOnInit() {
  this.subscription = this.mys.myService().subscribe(
    res => {
      this.servicOutput = res,
      this.servicOutput.forEach(element => {
        this.pushFunc(element);
        }
      ),
      this.myObjects = this.tmpObj; //here collect all elements as an object and pass out of ngOnInit scope
    },
    error => this.error = error,
  )
}

pushFunc(element) {
  this.tmpObj.push(
    {
      id:    element.id,
      title: element.title
    }
  )
}

Upvotes: 4

Views: 4223

Answers (4)

Caltor
Caltor

Reputation: 2756

Angular doesn't detect changes within an array. It only detects when the reference to the array itself changes. To get the html to re-render you need to use one of the following methods which will alert Angular that something has changed.

Method 1 - Use rest / spread operator instead of a push to change the array

Kudos to Rushi Patel for this method.

this.myObjects = [...this.myObjects, this.newObj[0]];

Method 2 - Use rest / spread operator to change array reference after a push

this.myObjects.push(this.newObj[0]);
this.myObjects = [...this.myObjects];

Method 3 - Use JSON.stringify/parse to change array reference after a push

this.myObjects.push(this.newObj[0]);
this.myObjects = JSON.parse(JSON.stringify(this.myObjects));

Method 4 - Use detectChanges() to notify Angular that something has changed

This is also suggested in https://stackoverflow.com/a/57689299/470014

constructor(private changeDetectorRef: ChangeDetectorRef) { }

public testMethod() {
    this.myObjects.push(this.newObj[0]);
    this.changeDetectorRef.detectChanges();}

Upvotes: 2

Shlomi Tubul
Shlomi Tubul

Reputation: 48

assuming your service return any value, you can call detectchanges method after each arr.push(), because angular does not recognize changes like push / pop automatically. Like so:

constructor(private changeDetectorRef: ChangeDetectorRef) { }

public testMethod() {
    this.arr.push({name: 'test'});
    this.changeDetectorRef.detectChanges();
}

Upvotes: 0

David
David

Reputation: 71

if in this.tmpObj you get all data and the problem is when you try to assign this data to this.myObjects then use slice method from arrays this.myObjects = this.tmpObj.slice()

Upvotes: 0

talhature
talhature

Reputation: 2165

Angular's change detection mechanism does not handle the content change of an array. You can either change the referance of the array as xdecdec suggested earlier in comments or you can implement your own ngDoChange so that you can implement your own way to detect the change of array content.

Check this answer for further explanation on implementing ngDoChange: https://stackoverflow.com/a/42962723/11420760

Upvotes: 2

Related Questions