angular - ¿Por qué necesito llamar a detectChanges() con la estrategia de detección de cambios predeterminada?
Estoy trabajando en una aplicación de Angular 4, pero tengo un problema en la medida en que tengo que llamar a this.changeDetectorRef.detectChanges(); para actualizar la vista cuando el modelo cambia. Por ejemplo, tengo este código que es para la paginación:
changePage(pageNumber) {
this.currentPage = pageNumber;
// why do I need to do this?
this.changeDetectorRef.detectChanges();
}
He establecido explícitamente la estrategia de detección de cambios en el componente a ChangeDetectionStrategy.Default, pero esto no tiene ningún efecto. También está ocurriendo aquí al suscribirse a un observable:
showResults(preference) {
this.apiService.get('dining_autocomplete/', `?search=${preference}`)
.subscribe((results) => {
this.searchResults = results;
// why do I need to do this?
this.changeDetectorRef.detectChanges();
});
}
Si hago console.log() de this.searchResults en TypeScript, obtengo los resultados esperados, pero si uso {{ searchResults }} en el HTML, no se actualiza hasta que ocurre algún otro evento, presumiblemente cuando pasa por otro ciclo de digestión.
¿Qué podría estar pasando?
== EDITAR ===========================================================
El código de mi componente se ve así:
import {ChangeDetectorRef, Component, Input, OnChanges} from "@angular/core";
import * as _ from 'lodash';
@Component({
selector: 'dining-search-results',
templateUrl: './dining-search-results.template.html',
styleUrls: ['./dining-search-results.style.scss'],
})
export class DiningSearchResultsComponent {
@Input() searchResults: any[];
@Input() hotTablesOnly: boolean = false;
@Input() memberBenefitsOnly: boolean = false;
numberOfTagsToDisplay: number = 3;
resultsPerPage: number = 5;
currentPage: number = 1;
constructor(private changeDetectorRef: ChangeDetectorRef) {
}
get filteredResults() {
return this.searchResults ?
this.searchResults.filter((r) => !((this.hotTablesOnly && !r.has_hot_table)
|| (this.memberBenefitsOnly && !r.has_member_benefit))) : [];
}
get pagedResults() {
return _.chain(this.filteredResults)
.drop(this.resultsPerPage * (this.currentPage - 1))
.take(this.resultsPerPage)
.value();
}
get totalPages(): number {
return Math.ceil(this.filteredResults.length / this.resultsPerPage);
}
getInitialTags(tagsArray: any[], count: number): any[] {
return _.take(tagsArray, count);
}
changePage(pageNumber) {
this.currentPage = pageNumber;
// why do I need to do this?
this.changeDetectorRef.detectChanges();
}
}
Cuando se llama a changePage(), y se actualiza this.currentPage, los cambios no se reflejan en el HTML a menos que llame a detectChanges().
Respuesta #1
He resuelto el problema.
Otro componente que enviaba notificaciones a este componente estaba ejecutando Observable.fromEvent() fuera de la zona de Angular, por lo que la detección de cambios no ocurría automáticamente en respuesta a estos eventos. ¡Esta publicación sobre zonas y esta publicación de StackOverflow sobre el problema contenían la solución!