Deshacer el libro Angular 2, Capítulo 1, Ejemplo 5

La página muestra una lista de inmersiones, tiene un “agregar nueva inmersión”, “inmersiones claras” y un cuadro de búsqueda, que filtra la lista mostrada a medida que escribe en ella.

Esta es la plantilla:

My Latest Dives (Angular/TypeScript)

{{dive.site}}

{{dive.location}}

{{dive.depth}} feet | {{dive.time}} min

Este es el código del componente:

 import {Component} from '@angular/core'; @Component({ selector: 'divelog', templateUrl: 'app/dive-log.template.html' }) export class DiveLogComponent { public dives = []; private _index = 0; private _stockDives = [ { site: 'Abu Gotta Ramada', location: 'Hurghada, Egypt', depth: 72, time: 54 }, { site: 'Ponte Mahoon', location: 'Maehbourg, Mauritius', depth: 54, time: 38 }, { site: 'Molnar Cave', location: 'Budapest, Hungary', depth: 98, time: 62 }]; public enableAdd() { return this._index < this._stockDives.length; } public addDive() { if (this.enableAdd()) { this.dives.push(this._stockDives[this._index++]); } } public clearDives() { this.dives = []; this._index = 0; } } 

Este es el código de filtro:

 import {Pipe, PipeTransform} from '@angular/core'; @Pipe({name: 'contentFilter'}) export class ContentFilterPipe implements PipeTransform { transform(value: any[], searchFor: string) : any[] { if (!searchFor) return value; searchFor = searchFor.toLowerCase(); return value.filter(dive => dive.site.toLowerCase().indexOf(searchFor) >= 0 || dive.location.toLowerCase().indexOf(searchFor) >= 0 || dive.depth.toString().indexOf(searchFor) >= 0 || dive.time.toString().indexOf(searchFor) >= 0); } } 

El filtro se invoca y la lista se vuelve a entregar cada vez que escribo en el cuadro de búsqueda, pero no cuando hago clic en el botón “Agregar”. Si tengo algo en el cuadro de búsqueda, el botón “agregar” no da como resultado el cambio de la lista de buceo, aunque el contenido del cuadro de búsqueda permite que se muestren los nuevos elementos. ¿Cómo cambio el código para que al hacer clic en el botón “agregar” se produzca la remisión de la lista de inmersiones que se muestra?

Tienes un tubo puro

su transform método se ejecutará solo cuando detecte un cambio puro en el valor de entrada.

Para su caso

 *ngFor="let dive of dives | contentFilter:searchBox.value" 

el valor de entrada será dives y searchBox.value

De acuerdo con la guía angular2 en tuberías:

Un cambio puro es un cambio en un valor de entrada primitivo (String, Number, Boolean, Symbol) o una referencia de objeto modificada (Date, Array, Function, Object).

  • Cuando se agrega una dive , la referencia de la matriz (inmersiones) no se cambia; por lo tanto, el método de transform no se ejecuta.
  • Cuando se escribe algo en la entrada del filtro, searchBox.value sí cambia, por lo que se ejecuta la transform .

Así que una de las posibles soluciones es tener siempre una nueva matriz de referencia cada vez que se agregue un div:

Simplemente reemplace:

 this.dives.push(this._stockDives[this._index++]); 

con:

 this.dives = this.dives.concat(this._stockDives[this._index++]); 

o:

 this.dives = [...this.dives, this._stockDives[this._index++]]; 

La segunda forma de hacerlo funcionar es utilizar tubería impura :

 @Pipe({name: 'contentFilter', pure: false })