Búsqueda de sitios web

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!

Artículos relacionados