La vista no está actualizada en el cambio en Angular2

Empecé a explorar Angular2 (voy con Angular1 y un poco de fondo React) y me quedé con un problema.

Quiero vincular ciertas pulsaciones de teclas a acciones en mi componente, por lo que he decidido utilizar el ciclo de vida de Angular2 para vincular / desvincular acciones.

Sin embargo, si hago algo desde una callback de Mousetrap, funciona, pero no se procesa y un cambio no es visible hasta que se ejecuta un ciclo de resumen.

¿Debo ejecutar algo explícitamente para actualizar una vista?

¿Podría alguien ayudarme a descubrir qué está pasando? Cualquier ayuda será muy apreciada.


import {Component} from 'angular2/core'; const Mousetrap = require('mousetrap'); @Component({ template: `
Video template: Mode {{ mode }}
` }) export class Video { public mode: number; constructor() { this.mode = 0; } ngOnInit() { console.log('hello Video component'); Mousetrap.bind('d', () => console.log('this.mode=', this.mode)); Mousetrap.bind('i', () => this.incrementMode()); // doesn't work this.incrementMode(); // works this.incrementMode(); // works setTimeout(() => this.incrementMode(), 4000); // works } incrementMode() { console.log('incMode', this.mode++); }; ngOnDestroy() { console.log('bye bye Video component'); Mousetrap.unbind(['d', 'i']); } }

Aunque la respuesta de @Günter es absolutamente correcta, quiero proponer una solución diferente.

El problema con la biblioteca Mousetrap es que crea su instancia fuera de la zona angular (ver aquí ). Pero para disparar la detección de cambios después de cada evento asíncrono, la instancia debe ser instanciada dentro de la zona angular . Tienes dos opciones para lograr esto:

  1. Usar dependency injection:
 bootstrap(App, [provide(Mousetrap, { useFactory: () => new Mousetrap() }) ]); // ... @Component({ selector: 'my-app', // ... }) export class App { constructor(@Inject(Mousetrap) mousetrap) { this.mousetrap = mousetrap; // ... } //... } 
  1. Solo crea una instancia de Mousetrap dentro del constructor:
 @Component({ selector: 'my-app', // ... }) export class App { constructor() { this.mousetrap = new Mousetrap(); // ... } //... } 

En ambos casos, tendrá la posibilidad de utilizar la instancia de mousetrap de esta manera:

 ngOnInit() { this.mousetrap.bind('i', () => this.incrementMode()); // It works now!!! // ... } 

Ahora no necesita usar ngZone.run() en cada llamada de bind . En caso de dependency injection, también puede utilizar esta instancia de mousetrap en cualquier componente / servicio de su aplicación (no solo en el componente de la App ).

Mira este truco . Yo uso dependency injection allí.

Si MouseTrap es algo fuera de Angular, es posible que necesites inyectar NgZone y ejecutar tu código como

  Mousetrap.bind('i', () => this.ngZone.run(() => this.incrementMode()));