Estoy usando un objeto javascript que tiene una devolución de llamada. Una vez que se activa la devolución de llamada, quiero llamar a una función dentro de un componente Angular2.
archivo HTML de ejemplo.
var run = new Hello('callbackfunction'); function callbackfunction(){ // how to call the function **runThisFunctionFromOutside** } <script> System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true }, packages: {'js/app': {defaultExtension: 'ts'}} }); System.import('js/app/main') .then(null, console.error.bind(console)); </script>Mi aplicación.component.ts
import {Component NgZone} from 'angular2/core'; import {GameButtonsComponent} from './buttons/game-buttons.component'; @Component({ selector: 'my-app', template: ' blblb' }) export class AppComponent { constructor(private _ngZone: NgZone){} ngOnInit(){ calledFromOutside() { this._ngZone.run(() => { this.runThisFunctionFromOutside(); }); } } runThisFunctionFromOutside(){ console.log("run"); }¿Cómo puedo llamar a la función runThisFunctionFromOutside que está dentro de App.component.ts?
Básicamente seguí esta respuesta , pero no quería que mi código "externo" supiera nada sobre NgZone. Este es app.component.ts:
import {Component, NgZone, OnInit, OnDestroy} from '@angular/core'; @Component({ selector: 'my-app', templateUrl: 'app.component.html' }) export class AppComponent implements OnInit, OnDestroy { constructor(private ngZone: NgZone) {} ngOnInit() { window.my = window.my || {}; window.my.namespace = window.my.namespace || {}; window.my.namespace.publicFunc = this.publicFunc.bind(this); } ngOnDestroy() { window.my.namespace.publicFunc = null; } publicFunc() { this.ngZone.run(() => this.privateFunc()); } privateFunc() { // do private stuff } }También tuve que agregar una definición para TypeScript para extender el objeto de la ventana. Pongo esto en typings.d.ts:
interface Window { my: any; }Llamar a la función desde la consola ahora es tan simple como:
my.namespace.publicFunc()Consulte también ¿Cómo exponer públicamente los métodos angulares 2?
Cuando se construya el componente, haga que se asigne a una variable global. Luego puede hacer referencia desde allí y llamar a los métodos. No olvide usar zone.run(() => { ... }) para que Angular reciba notificaciones sobre las ejecuciones de detección de cambios requeridas.
function callbackfunction(){ // window['angularComponentRef'] might not yet be set here though window['angularComponent'].zone.run(() => { runThisFunctionFromOutside(); }); } constructor(private _ngZone: NgZone){ window['angularComponentRef'] = {component: this, zone: _ngZone}; } ngOnDestroy() { window.angularComponent = null; } En la consola del navegador, debe cambiar de <topframe> a plunkerPreviewTarget.... porque Plunker ejecuta el código en un iFrame . Entonces corre
window['angularComponentRef'].zone.run(() => {window['angularComponentRef'].component.callFromOutside('1');})o
window.angularComponentRef.zone.run(() => {window.angularComponentRef.componentFn('2');})Un enfoque alternativo
sería enviar eventos fuera de Angular y escucharlos en Angular como se explica en Angular 2: comunicación de funciones mecanografiadas con bibliotecas js externas
Plunker ejemplo2 (de los comentarios)
A continuación se muestra una solución.
function callbackfunction(){ window.angularComponent.runThisFunctionFromOutside(); } <script> System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true }, packages: {'js/app': {defaultExtension: 'ts'}} }); System.import('js/app/main') .then(null, console.error.bind(console)); </script>Mi aplicación.component.ts
import {Component NgZone} from 'angular2/core'; import {GameButtonsComponent} from './buttons/game-buttons.component'; @Component({ selector: 'my-app', template: ' blblb' }) export class AppComponent { constructor(private _ngZone: NgZone){ window.angularComponent = {runThisFunctionFromOutside: this.runThisFunctionFromOutside, zone: _ngZone}; } runThisFunctionFromOutside(){ console.log("run"); } }