2016-02-09 75 views
44

我正在使用具有回調的JavaScript對象。我希望一旦回調被觸發來調用Angular2組件中的函數。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

+0

你能給我們更多的環境?你在哪裏運行對象?你的回調是如何被調用的?謝謝! –

+0

在html中調用運行,在之外調用。 – Roninio

+0

好的。而回調? –

回答

42

參見How do expose angular 2 methods publicly?

W如果組件被構建,則將其自身分配給全局變量。然後你可以從那裏引用它並調用方法。 不要忘記使用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 2 - communication of typescript functions with external js libraries

Plunker example2解釋(從評論)

+0

出於興趣,注入'Window'提供者而不是直接將其附加到'window'對象會更好嗎? –

+0

也許吧。但起初它應該可以工作,我想。 –

+2

如果縮小更改名稱,則可能更好地分配函數引用而不是類引用('window.angularComponentRef = {zone:zone,/ * component:this */componentFn:this.callFromOutside};')。 –

6

下面是一個解決方案。

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"); 
    } 
} 
+0

如何通過runThisFunctionFromOutside函數訪問在AppComponent中定義的變量? – Starwave

+1

@Starwave:您需要將組件上下文綁定到回調函數:「runThisFunctionFromOutside:this.runThisFunctionFromOutside.bind(this)」 – gradosevic

+0

完美地工作!謝謝 – Manny

29

我基本上遵循this answer,但我不希望我的 「外部」 的代碼來了解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() 
+1

非常感謝你爲我工作 –

+0

這對我有用,但publicFunc總是被調用兩次? – daniel

+0

這是更清潔的代碼,它爲我工作,謝謝! – Caner

0

不使用全局變量的另一種方法是使用通過控制對象並將其屬性綁定到要顯示的變量和方法。

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> 
0

我使用fullCalendar庫,其回調從角區域外正在返回的回調「eventClick」時,引起我的應用程序有局部的和不可靠的效果也有類似的情況。爲了提高輸出事件,我可以將區域方法和封閉引用組合在一起,如下所示。一旦我開始在zone.run()方法內執行事件並且它的效果再次可預測並且通過角度變化檢測來拾取。希望這可以幫助某人。

constructor(public zone: NgZone) { // code removed for clarity 
} 

ngOnInit() { 
    this.configureCalendar(); 
} 

private configureCalendar() { 
    // FullCalendar settings 
    this.uiConfig = { 
     calendar: { // code removed for clarity 

     } 
    }; 

    this.uiConfig.calendar.eventClick = this.onEventClick(); 

} 

private onEventClick() { 
    const vm = this; 

    return function (event, element, view) { 
     vm.zone.run(() => { 
      vm.onSequenceSelected.emit(event.sequenceSource);      
     }); 

     return false; 

    }; 
} 
0

只是增加@Dave Kennedy

從控制檯調用的函數現在簡單:

my.namespace.publicFunc()

1)如果我們試圖訪問我們的組件來自不同域的公共方法,您將陷入CORS問題(如果服務器和客戶端代碼都駐留在同一臺機器上,則可以解決跨源問題)。

2)如果你要打電話從使用javascript服務器這種方法,你將不得不使用window.opener.my.namespace.publicFunc()代替window.my.namespace.publicFunc():

window.opener.my.namespace.publicFunc();

相關問題