Búsqueda de sitios web

TypeScript - Angular: El pipe no funciona


He creado una tubería que no funciona bien. El código parece ser sencillo y claro, pero no logro entender qué está mal.

¿Alguna idea?

Mi app.module:

import { HeroModule } from "./hero/hero.module";

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule, HeroModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Mi hero.module:

import { HeroComponent } from './hero.component';
import { FlyersPipe } from '../pipes/flyers.pipe';

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [HeroComponent, FlyersPipe],
  exports: [HeroComponent, FlyersPipe]
})
export class HeroModule { }

Mi flyers.pipe.ts:

import { Pipe, PipeTransform } from '@angular/core';
import { Hero } from '../model/hero';

@Pipe({
  name: 'appflyers'
})
export class FlyersPipe implements PipeTransform {

  transform(heroes: Array<Hero>, args?: any): any {
    console.info(heroes);
    return heroes.filter(hero => hero.canFly);
  }

}

Por último, mi hero.component.html:

<div *ngFor="let hero of heroes | appflyers">
    {{hero | json}}
</div>

EDITAR

Estoy agregando héroes en la propiedad heroes del HeroComponent usando este código:

<input type="text" #box
          (keyup.enter)="addHero(box.value); box.value=''"
          placeholder="hero name">
  <input type="checkbox" [checked]="canFly" (change)="canFly = !canFly"/>

hero.component.ts:

import { Component, OnInit } from '@angular/core';
import { Hero } from '../model/hero';

@Component({
  selector: 'app-hero',
  templateUrl: './hero.component.html',
  styleUrls: ['./hero.component.css']
})
export class HeroComponent implements OnInit {

  private heroes: Array<Hero> = new Array<Hero>();
  private canFly: boolean = true;

  constructor() { }

  ngOnInit() {
  }

  private addHero(name: string) {
    this.heroes.push(new Hero(name, null, this.canFly));
  }

  private reset() { this.heroes = this.heroes.slice(); }

}

Respuesta #1

Creo que tu escenario es exactamente lo que describe la documentación del pipe

Observa el comportamiento extraño en el ejemplo en vivo/ejemplo de descarga: cuando agregas héroes que vuelan, ninguno de ellos se muestra bajo "Héroes que vuelan."

Los pipes son puros por defecto, lo que significa que no se ejecutarán en la detección de cambios si la entrada no cambia.

Angular ejecuta un pipe puro solo cuando detecta un cambio puro en el valor de entrada. Un cambio puro es ya sea un cambio en un valor de entrada primitivo (String, Number, Boolean, Symbol) o una referencia de objeto cambiada (Date, Array, Function, Object).

Angular ignora los cambios dentro de objetos (compuestos). No llamará a un pipe puro si cambias un mes de entrada, agregas a un array de entrada o actualizas una propiedad de un objeto de entrada

Para que funcione, puedes convertir tu tubería en una tubería impura, lo que significa que se ejecutará durante cada ciclo de detección de cambios. Está bien si la operación realizada por la tubería es rápida.

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

Otra solución es mantener tu pipe puro y cambiar la referencia al arreglo (por ejemplo, usando el operador spread) cuando agregues un nuevo héroe

private addHero(name: string) 
{
    this.heroes = [...this.heroes, new Hero(name, null, this.canFly)];
}