简体   繁体   English

如何从独立的纯 JavaScript 函数调用 Angular 4 方法?

[英]How to call an Angular 4 method from a standalone plain JavaScript function?

I'd like to be able to pass some data\\propagate events from a plugin on the page to my Angular 4 app.我希望能够将一些数据\\传播事件从页面上的插件传递到我的 Angular 4 应用程序。

More specifically, in my case data\\events are generated inside a Silverlight plugin app that is next to the Angular app on the page.更具体地说,在我的情况下,数据\\事件是在页面上 Angular 应用程序旁边的 Silverlight 插件应用程序中生成的。

I have the following solution in my mind:我有以下解决方案:

  • Create a global JS function which gets called from Silverlight (since this seems to be the simplest way to get data out from Silverlight) when there is a need to talk to Angular side.创建一个从 Silverlight 调用的全局 JS 函数(因为这似乎是从 Silverlight 获取数据的最简单方法),以便在需要与 Angular 端对话时。
  • The function, in turn, calls some Angular class method passing data collected from Silverlight.反过来,该函数调用一些 Angular 类方法,传递从 Silverlight 收集的数据。

As an illustration to that (excluding the Silverlight part), we could have the following.作为说明(不包括 Silverlight 部分),我们可以有以下内容。

A method as an entry point on the Angular side:作为 Angular 侧入口点的方法:

export class SomeAngularClass {
    public method(data: any): void {
        ...
    }
}

And somewhere outside the Angular realm, we add a global plain JavaScript function (to be called by Silverlight):在 Angular 领域之外的某个地方,我们添加了一个全局纯 JavaScript 函数(由 Silverlight 调用):

window.somePlainJsFunction = function (data) {
    // How to consume SomeAngularClass.method() from here?
}

The question is: how can we call the Angular class methods from a plain JavaScript function?问题是:我们如何从一个普通的 JavaScript 函数调用 Angular 类方法?

As pointed by @Dumpen, you can use @HostListener to get the custom event dispatched from javascript outside of Angular.正如@Dumpen 所指出的,您可以使用@HostListener 来获取从 Angular 之外的 javascript 调度的自定义事件。 If you also want to send parameters, then you can send them by adding them as detail object.如果您还想发送参数,则可以通过将它们添加为详细信息对象来发送它们。

In Javascript:在 JavaScript 中:

function dispatch(email, password) {
    var event = new CustomEvent('onLogin', {
        detail: {
            email: email,
            password: password
        }
    })
    window.dispatchEvent(event);
}

Then you can call this method on button click.然后您可以在单击按钮时调用此方法。

Now to listen to this dispatched event in Angular, you can create function in Angular component and add @HostListener to it like below:现在要在 Angular 中收听这个调度事件,您可以在 Angular 组件中创建函数并将@HostListener 添加到它,如下所示:

@HostListener('window:onLogin', ['$event.detail'])
onLogin(detail) {
    console.log('login', detail);
}

This code you can add in any component.您可以在任何组件中添加此代码。 I have added it to my root component - AppComponent我已将它添加到我的根组件 - AppComponent

You can use a events, so you have the JavaScript send an event that you are listening for in your service.您可以使用事件,这样您就可以让 JavaScript 发送您在服务中侦听的事件。

The CustomEvent is a new feature so you might need to polyfill it: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent CustomEvent是一项新功能,因此您可能需要对其进行 polyfill: https : //developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent

JavaScript: JavaScript:

var event = new CustomEvent("CallAngularService");

window.dispatchEvent(event);

Angular:角度:

@HostListener("window:CallAngularService")
onCallAngularService() {
  // Run your service call here
}

I think this is what you are looking for service out side angular我认为这就是您正在寻找的外角服务

You can create function/class outside Angular and provide as a value in the angular.您可以在 Angular 之外创建函数/类,并在 angular 中提供一个值。 in this way you can handle both angular and non angular stuffs together:通过这种方式,您可以同时处理有角和无角的东西:

class SomePlainClass {
  ...
}
window.somePlainJsFunction = new SomePlainClass();

@NgModule({
  providers: [{provide: SomePlainClass, useValue: window.somePlainJsFunction}],
  ...
})
class AppModule1 {}

@NgModule({
  providers: [{provide: SomePlainClass, useValue: window.somePlainJsFunction}],
  ...
})
class AppModule2 {}

class MyComponent {
  constructor(private zone:NgZone, private SomePlainClass:SharedService) {
    SomePlainClass.someObservable.subscribe(data => this.zone.run(() => {
      // event handler code here
    }));
  }
}

The way it should be done depends on particular case, especially on the precedence.应该采取的方式取决于特定情况,尤其是优先级。

If Silverlight aplication is initialized before Angular application, and window.somePlainJsFunction is called before finishing Angular application initialization, this will result in race condition.如果在 Angular 应用程序之前初始化 Silverlight 应用程序,并且在完成 Angular 应用程序初始化之前调用window.somePlainJsFunction ,这将导致竞争条件。 Even if there was an acceptable way to get Angular provider instance externally, the instance wouldn't exist during somePlainJsFunction call.即使有一种可接受的方式从外部获取 Angular 提供程序实例,该实例在somePlainJsFunction调用期间也不存在。

If window.somePlainJsFunction callback is called after Angular bootstrap, window.somePlainJsFunction should be assigned inside Angular application, where SomeAngularClass provider instance is reachable:如果Angular 引导程序之后调用window.somePlainJsFunction回调,则应Angular 应用程序内部分配window.somePlainJsFunction ,其中SomeAngularClass提供程序实例可访问:

window.somePlainJsFunction = function (data) {
    SomeAngularClass.method();
}

If window.somePlainJsFunction callback is called before Angular bootstrap, it should provide global data for Angular application to pick up:如果Angular 引导程序之前调用window.somePlainJsFunction回调,它应该为 Angular 应用程序提供全局数据以获取:

window.somePlainJsFunction = function (data) {
    window.angularGlobalData = data;
}

Then window.angularGlobalData can be used inside Angular, either directly or as a provider.然后window.angularGlobalData可以在 Angular 中直接使用或作为提供者使用。

Working Example工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM