typescript - Array-ul creat cu array.push() are elemente, dar nu am putut folosi Angular


Am 2 Array<object>. Unul dintre ele are elemente inițiale și celălalt își are elementele adăugate prin array.push() în ngOnInit. La final, ambele au elementele în output, dar html-ul nu randă elementele care au fost adăugate cu .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)

codul

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,
  )
}

Rezolvat

Notificarea principală a fost this.myObjects=this.tmpObj după forEach care colectează toate elementele pentru a le transmite în afara domeniului ngOnInit, am editat codul meu astfel:

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
    }
  )
}

Răspuns #1

Mecanismul de detectare a schimbărilor din Angular nu gestionează modificarea conținutului unui array. Poți fie să schimbi referința array-ului așa cum a sugerat xdecdec mai devreme în comentarii, fie poți să implementezi propriul tău ngDoChange astfel încât să poți implementa propria ta metodă de a detecta modificarea conținutului array-ului.

Verifică acest răspuns pentru o explicație suplimentară despre implementarea ngDoChange: https://stackoverflow.com/a/42962723/11420760

Răspunsul #2

Angular nu detectează modificările din cadrul unui array. Detectează doar atunci când se schimbă referința către array-ul în sine. Pentru ca HTML-ul să se re-redeseze, trebuie să folosești una dintre următoarele metode care vor alerta Angular că ceva s-a schimbat.

Metoda 1 - Folosește operatorul rest/spread în loc de push pentru a modifica array-ul

Felicitări lui Rushi Patel pentru această metodă.

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

Metoda 2 - Folosește operatorul rest/spread pentru a schimba referința array-ului după un push

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

Metoda 3 - Folosește JSON.stringify/parse pentru a schimba referința unui array după un push

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

Metoda 4 - Folosește detectChanges() pentru a notifica Angular că ceva s-a schimbat

Acest lucru este sugerat și în https://stackoverflow.com/a/57689299/470014

constructor(private changeDetectorRef: ChangeDetectorRef) { }

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