简体   繁体   English

Angular2 - 如何从应用程序外部调用组件函数

[英]Angular2 - how to call component function from outside the app

I am using a javascript Object that has a callback.我正在使用具有回调的 javascript 对象。 Once the callback is fired I want to call a function inside an Angular2 component.一旦回调被触发,我想在 Angular2 组件中调用一个函数。

example HTML file.示例 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>

My App.component.ts我的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");
}

How can i call the function runThisFunctionFromOutside which is inside App.component.ts我如何调用App.component.ts内的函数 runThisFunctionFromOutside

I basically followed this answer , but I didn't want my "outside" code to know anything about NgZone.我基本上遵循了这个答案,但我不希望我的“外部”代码了解有关 NgZone 的任何信息。 This is app.component.ts:这是 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
  }
}

I also had to add a definition for TypeScript to extend the window object.我还必须为 TypeScript 添加一个定义来扩展 window 对象。 I put this in typings.d.ts:我把它放在typings.d.ts中:

interface Window { my: any; }

Calling the function from the console is now as simple as:从控制台调用该函数现在非常简单:

my.namespace.publicFunc()

See also How do expose angular 2 methods publicly?另请参阅如何公开公开 angular 2 方法?

When the component is constucted make it assign itself to a global variable.当组件被构造时,让它将自己分配给一个全局变量。 Then you can reference it from there and call methods.然后你可以从那里引用它并调用方法。 Don't forget to use zone.run(() => { ... }) so Angular gets notified about required change detection runs.不要忘记使用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 example1Plunker 示例 1

In the browser console you have to switch from <topframe> to plunkerPreviewTarget.... because Plunker executes the code in an iFrame .在浏览器控制台中,您必须从<topframe>切换到plunkerPreviewTarget....因为 Plunker 在iFrame执行代码。 Then run然后运行

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

or或者

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

An alternative approach另一种方法

would be to dispatch events outside Angular and listen to them in Angular like explained in Angular 2 - communication of typescript functions with external js libraries将是在 Angular 之外调度事件并在 Angular 中收听它们,就像在Angular 2 中解释的那样- typescript 函数与外部 js 库的通信

Plunker example2 (from the comments)Plunker 示例 2 (来自评论)

Below is a solution.下面是一个解决方案。

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>

My App.component.ts我的 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");
    }
}

An other approach without using global variables is to use pass a control object and bind its properties to the variables and methods to expose.另一种不使用全局变量的方法是使用传递控制对象并将其属性绑定到要公开的变量和方法。

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>

I had a similar situation when using the callback 'eventClick' of the fullCalendar library, whose callbacks are returning from outside the angular zone, causing my application to have partial and unreliable effects.我在使用fullCalendar库的回调 'eventClick' 时遇到了类似的情况,它的回调从 angular zone 外部返回,导致我的应用程序具有部分和不可靠的效果。 I was able to combine the zone approach and a closure reference to the component as seen below in order to raise an output event.我能够将区域方法和对组件的闭包引用结合起来,如下所示,以引发输出事件。 Once I started executing the event inside of the zone.run() method the event and it's effects were once again predictable and picked up by angular change detection.一旦我开始在 zone.run() 方法内执行事件,该事件及其影响将再次可预测并被角度变化检测检测到。 Hope this helps someone.希望这可以帮助某人。

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;

    };
}

Just adding to @Dave Kennedy :只是添加到@Dave Kennedy

Calling the function from the console is now as simple as:从控制台调用该函数现在非常简单:

my.namespace.publicFunc()

1) If we try to access our component's public method from a different domain you will get caught into CORS issue (the cross origin problem, can be solved if both server and client code resides in same machine). 1)如果我们尝试从不同的域访问我们组件的公共方法,您将陷入 CORS 问题(跨域问题,如果服务器和客户端代码驻留在同一台机器上,则可以解决)。

2) if you were to call this method from server using javascript, you will have to use window.opener.my.namespace.publicFunc() instead of window.my.namespace.publicFunc(): 2)如果您要使用 javascript 从服务器调用此方法,则必须使用window.opener.my.namespace.publicFunc()而不是window.my.namespace.publicFunc():

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

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

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