Saltar al contenido

Angular 2: la vista no se actualiza después de los cambios de modelo

Solución:

Puede ser que el código en su servicio de alguna manera salga de la zona de Angular. Esto rompe la detección de cambios. Esto debería funcionar:

import {Component, OnInit, NgZone} from 'angular2/core';

export class RecentDetectionComponent implements OnInit {

    recentDetections: Array<RecentDetection>;

    constructor(private zone:NgZone, // <== added
        private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => { 
                 this.zone.run(() => { // <== added
                     this.recentDetections = recent;
                     console.log(this.recentDetections[0].macAddress) 
                 });
        });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        timer.subscribe(() => this.getRecentDetections());
    }
}

Para conocer otras formas de invocar la detección de cambios, consulte Activar la detección de cambios manualmente en Angular

Las formas alternativas de invocar la detección de cambios son

ChangeDetectorRef.detectChanges()

para ejecutar inmediatamente la detección de cambios para el componente actual y sus hijos

ChangeDetectorRef.markForCheck()

para incluir el componente actual la próxima vez que Angular ejecute la detección de cambios

ApplicationRef.tick()

para ejecutar la detección de cambios para toda la aplicación

Originalmente es una respuesta en los comentarios de @Mark Rajcok, pero quiero colocarlo aquí como probado y funcionado como una solución usando ChangeDetectorRef, veo un buen punto aquí:

Otra alternativa es inyectar ChangeDetectorRef y llama
cdRef.detectChanges() en lugar de zone.run(). Esto podría ser más eficiente, ya que no ejecutará la detección de cambios en todo el árbol de componentes como zone.run() lo hace. – Mark Rajcok

Entonces el código debe ser como:

import {Component, OnInit, ChangeDetectorRef} from 'angular2/core';

export class RecentDetectionComponent implements OnInit {

    recentDetections: Array<RecentDetection>;

    constructor(private cdRef: ChangeDetectorRef, // <== added
                private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => {
                this.recentDetections = recent;
                console.log(this.recentDetections[0].macAddress);
                this.cdRef.detectChanges(); // <== added
            });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        timer.subscribe(() => this.getRecentDetections());
    }
} 

Editar: Utilizando .detectChanges() dentro de la subcibe podría dar lugar a un problema Intento de utilizar una vista destruida: detectChanges

Para solucionarlo necesitas unsubscribe antes de destruir el componente, por lo que el código completo será como:

import {Component, OnInit, ChangeDetectorRef, OnDestroy} from 'angular2/core';

export class RecentDetectionComponent implements OnInit, OnDestroy {

    recentDetections: Array<RecentDetection>;
    private timerObserver: Subscription;

    constructor(private cdRef: ChangeDetectorRef, // <== added
                private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => {
                this.recentDetections = recent;
                console.log(this.recentDetections[0].macAddress);
                this.cdRef.detectChanges(); // <== added
            });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        this.timerObserver = timer.subscribe(() => this.getRecentDetections());
    }

    ngOnDestroy() {
        this.timerObserver.unsubscribe();
    }

}

En mi caso, tuve un problema muy similar. Estaba actualizando mi vista dentro de una función que estaba siendo llamada por un componente principal, y en mi componente principal olvidé usar @ViewChild (NameOfMyChieldComponent). Perdí al menos 3 horas solo por este estúpido error. es decir: No necesitaba usar cualquiera de esos métodos:

  • ChangeDetectorRef.detectChanges ()
  • ChangeDetectorRef.markForCheck ()
  • ApplicationRef.tick ()
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *