Angular2 – 如何从应用程序外部调用组件函数
我正在使用一个有callback的JavaScript对象。 我希望一旦callback被触发来调用Angular2组件中的函数。
示例HTML文件。
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>
我的App.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"); }
我怎样才能调用函数runThisFunctionFromOutside是在App.component.ts内
另请参见如何公开angular2方法?
当构build组件时,将它自己分配给一个全局variables。 然后你可以从那里引用它并调用方法。 不要忘记使用zone.run(() => { ... })
以便Angular获得有关所需更改检测运行的通知。
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; }
Plunker example1
在浏览器控制台中,您必须从<topframe>
切换到plunkerPreviewTarget....
因为Plunker在iFrame
执行代码。 然后运行
window['angularComponentRef'].zone.run(() => {window['angularComponentRef'].component.callFromOutside('1');})
要么
window.angularComponentRef.zone.run(() => {window.angularComponentRef.componentFn('2');})
另一种方法
将在Angular之外发送事件,并在Angular中倾听他们,就像在Angular 2中解释的那样- 使用外部js库
Plunker example2 (来自评论)
我基本上遵循这个答案 ,但是我不希望我的“外部”代码知道关于NgZone的任何事情。 这是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 } }
我还必须为TypeScript添加一个定义来扩展窗口对象。 我把这个放在typings.d.ts中:
interface Window { my: any; }
从控制台调用函数现在简单如下:
my.namespace.publicFunc()
下面是一个解决scheme。
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>
我的App.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"); } }
另一种不使用全局variables的方法是使用传递一个控制对象,并将其属性绑定到要显示的variables和方法。
export class MyComponentToControlFromOutside implements OnChanges { @Input() // object to bind to internal methods control: { openDialog, closeDialog }; ngOnChanges() { if (this.control) { // bind control methods to internal methods this.control.openDialog = this.internalOpenDialog.bind(this); this.control.closeDialog = this.internalCloseDialog; } } internalOpenDialog(): Observable<boolean> { // ... } internalCloseDialog(result: boolean) { // ... } }
export class MyHostComponent { controlObject= {}; }
<my-component-to-control [control]="controlObject"></my-component-to-control> <a (click)="controlObject.open()">Call open method</a>