如何公开公开角度2方法?

时间:2016-02-08 18:05:35

标签: javascript angular

我目前正致力于将Backbone项目移植到Angular 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!');

无论哪种方式,我希望公开曝光方法,以便可以从angular 2应用程序外部调用。

这是我们在骨干网上所做的事情,但我想我的Google foo不够强大,无法使用angular找到一个好的解决方案。

我们宁愿只公开一些方法并列出公共api,所以如果你有这方面的提示,那将是一个额外的好处。 (我有想法,但欢迎其他人。)

5 个答案:

答案 0 :(得分:23)

只需让组件在全局地图中注册,您就可以从那里访问它。

使用构造函数或ngOnInit()或任何其他lifecycle hooks来注册组件,并使用ngOnDestroy()取消注册。

当您从Angular外部调用Angular方法时,Angular无法识别模型更改。这就是Angulars NgZone的用途。 要获得对Angular区域的引用,只需将其注入构造函数

即可
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');})

答案 1 :(得分:12)

这就是我做到的。我的组件如下。别忘了导入NgZone。这是最重要的部分。 NgZone让角度理解外部环境。通过区域运行功能允许您从在Angular区域外执行的任务重新进入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');
        }
    }

现在让我们从外面调用它。在我的情况下,我想通过我的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>

如果您只是在开发者控制台中键入以下内容并按Enter键,它将调用公开的方法,并且“这个工作完美”将打印在控制台上。

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

权利只是一些在此处作为参数传递的值。

答案 2 :(得分:4)

我正在检查代码,而且我已经面临区域可能不是必需的。 没有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>

这对我有用。

答案 3 :(得分:1)

问题在于Angular的组件被转换为不像常规JavaScript代码那样易于访问的模块。访问模块功能的过程取决于模块的格式。

Angular2类可以包含可以在不实例化新对象的情况下定义的静态成员。您可能希望将代码更改为:

    imageNames = dir(fullfile(workingDir,'*.png')); 

答案 4 :(得分:0)

超级简单的解决方案!!使用外部别名保存组件或功能

declare var exposedFunction;
@Component({
  templateUrl: 'app.html'
})
export class MyApp {
    constructor(public service:MyService){
    exposedFunction = service.myFunction;
}

在index.html头上添加

<script>
    var exposedFunction;
</script>

内部公开功能请勿使用。参数,如果需要它们,则必须使用闭包使其起作用

这在离子模式下尤其有用,它可以测试Web上的设备通知而不是设备上的通知