2016-02-08 25 views
15

我目前正在將Backbone項目移植到Angular 2項目(顯然有很多更改),並且其中一個項目需求需要某些方法可公開訪問。如何公開角度2方法?

一個簡單的例子:

組件

@component({...}) 
class MyTest { 
    private text:string = ''; 
    public setText(text:string) { 
     this.text = text; 
    } 
} 

很顯然,我可以有<button (click)="setText('hello world')>Click me!</button>,我也想這樣做,以及。但是,我希望能夠公開訪問它。

喜歡這個

<button onclick="angular.MyTest.setText('Hello from outside angular!')"></click> 

或者這

// in the js console 
angular.MyTest.setText('Hello from outside angular!'); 

無論哪種方式,我希望被公開曝光的方法,因此可以從角2應用程序外部調用。

這是我們在骨幹網上做的事情,但我想我的Google foo不夠強大,無法爲使用角度找到一個好的解決方案。

我們希望只公開一些方法並有一個公共apis的列表,所以如果您也有這樣做的提示,它將是一個額外的獎勵。 (我有想法,但其他人歡迎。)

+0

[Angular2 - 如何從應用程序外部調用組件函數]的可能副本(http://support.microsoft.com/kb/330970/zh-cn/)應用程序) –

+1

@DaveKennedy你意識到這個問題之前發佈的,對嗎? – Jacques

回答

17

只需將組件註冊到全局地圖中,然後就可以從中訪問它。

使用構造函數或ngOnInit()或任何其他lifecycle hooks來註冊組件並ngOnDestroy()註銷它。

當您從Angular外部調用Angular方法時,Angular無法識別模型更改。這是Angulars NgZone的用途。 要到角區的引用只是將其注入到構造

constructor(zone:NgZone) { 
} 

您可以讓zone本身在一個全局對象可用,以及或者只是執行區域內的組件內部的代碼。

例如

calledFromOutside(newValue:String) { 
    this.zone.run(() => { 
    this.value = newValue; 
    }); 
} 

或使用像

zone.run(() => { component.calledFromOutside(newValue); }); 

https://plnkr.co/edit/6gv2MbT4yzUhVUfv5u1b?p=preview

全局區域中引用你必須從<topframe>切換到plunkerPreviewTarget....瀏覽器控制檯,因爲Plunker執行代碼一個iFrame。然後運行

window.angularComponentRef.zone.run(() => {window.angularComponentRef.component.callFromOutside('1');}) 

window.angularComponentRef.zone.run(() => {window.angularComponentRef.componentFn('2');}) 
+0

好的,所以我需要爲我所有的公共方法制作輔助方法。順帶一提,非常感謝您的幫助。 – Jacques

+0

因此,在創建一個註冊任務的服務時,我遇到了同樣的問題,因爲我開始使用'zone.run(()=> {})之前'方法已註冊,我可以毫無問題地調用它但是,它似乎沒有運行更改檢測。 ();> { scope [callbackMethod](); });}};}}; };' 上面的'scope'是組件,我調用的方法是'callbackMethod'。 任何提示? – Jacques

+0

我很欣賞plunkr,但問題是我有一個外部服務正在window.widget對象上添加方法。我可以調用這些方法,但更改檢測不會觸發。它看起來像你的例子包含我沒有使用外部服務時使用的內容。 (我可能會取消該外部服務。)感謝您的幫助。 – Jacques

1

的問題是,角的組件transpiled成是不容易獲得定期的JavaScript代碼的模塊。訪問模塊功能的過程取決於模塊的格式。

Angular2類可以包含靜態成員,可以在不實例化新對象的情況下定義靜態成員。您可能需要更改您的代碼是這樣的:

@component({...}) 
class MyTest { 
    private static text: string = ''; 
    public static setText(text:string) { 
     this.text = text; 
    } 
} 
+0

我是否還需要一種方法公開公開? – Jacques

+0

要訪問Angular以外的組件,您應該查看經過轉換的JavaScript。通常,網頁通過訪問加載器加載組件(請參見[SystemJS](https://github.com/systemjs/systemjs)中的'System.import')。 – MatthewScarpino

+0

默認情況下,通過systemjs加載的組件不可訪問,查看已轉換的js不會幫助您使用system.register加載js。 Angular(或角等)甚至在全局範圍內都不可用,(http://stackoverflow.com/questions/34779126/detect-whether-angular2-is-loaded-on-a-page-when-using-systemjs ),我們不會在生產中使用systemjs。 – Jacques

3

這是我怎麼沒it.my分量提供below.dont忘記導入NgZone.it是最重要的部分here.its NgZone,讓角以瞭解外部環境。通過zone.run運行的功能允許您從Angular zone以外的任務重新進入Angular區域。我們在這裏需要它,因爲我們正在處理不在角度區域內的外部呼叫。

import { Component, Input , NgZone } from '@angular/core'; 
import { Router } from '@angular/router'; 

    @Component({ 
     selector: 'example', 
     templateUrl: './example.html', 
    }) 
    export class ExampleComponent { 
      public constructor(private zone: NgZone, private router: Router) { 

//exposing component to the outside here 
//componentFn called from outside and it in return calls callExampleFunction() 
     window['angularComponentReference'] = { 
      zone: this.zone, 
      componentFn: (value) => this.callExampleFunction(value), 
      component: this, 
     }; 
    } 

    public callExampleFunction(value: any): any { 
     console.log('this works perfect'); 
     } 
    } 

現在讓我們從outside.in我來說,我希望通過我的index.html.my的index.html的腳本標記到達這裏下面給出調用它。

<script> 

//my listener to outside clicks 
ipc.on('send-click-to-AT', (evt, entitlement) => 
electronClick(entitlement));; 

//function invoked upon the outside click event 

function electronClick(entitlement){ 
//this is the important part.call the exposed function inside angular 
//component 

    window.angularComponentReference.zone.run(() = 
    {window.angularComponentReference.componentFn(entitlement);}); 
} 
</script> 

,如果你只需要輸入下面的開發者控制檯並回車它會調用他的公開方法和「這個完美的作品」將在控制檯上打印。

window.angularComponentReference.zone.run(() = 
{window.angularComponentReference.componentFn(1);}); 

權利只是在這裏作爲參數傳遞的一些值。

+0

我剛剛跟着你的步驟結束''不能讀取'未定義'的屬性'區'這發生在''ClickEvent'在'home.cshtml'我的功能看起來像''** ps:**在開發者控制檯中,它工作正常。 – k11k2

+0

是否將Ngzone導入您的組件? –

0

我正在檢查代碼,並且我曾經面臨過該區域不是必需的。 沒有NgZone,它運作良好。

在組件構造做到這一點:

constructor(....) { 
    window['fncIdentifierCompRef'] = { 
     component = this 
    }; 
} 

以及根腳本試試這個:

<script> 
function theGlobalJavascriptFnc(value) { 
    try { 
    if (!window.fncIdentifierCompRef) { 
     alert('No window.fncIdentifierCompRef); 
     return; 
    } 
    if (!window.fncIdentifierCompRef.component) { 
     alert('No window.fncIdentifierCompRef.component'); 
     return; 
    } 
    window.fncIdentifierCompRef.component.PublicCmpFunc(value); 
    } catch(ex) {alert('Error on Cmp.PublicCmpFunc Method Call')} 
} 
</script> 

這工作給我。