首页 文章

Angular2 - 如何从应用程序外部调用组件功能

提问于
浏览
57

我正在使用具有回调的javascript对象 . 我希望一旦触发回调来调用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");
}

我如何调用App.component.ts中的函数 runThisFunctionFromOutside

6 回答

  • 49

    另见How do expose angular 2 methods publicly?

    构造组件时,将其自身分配给全局变量 . 然后你可以从那里引用它并调用方法 . 不要忘记使用 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');})
    

    An alternative approach

    将在Angular之外发送事件并在Angular中收听它们,如Angular 2 - communication of typescript functions with external js libraries中所述

    Plunker example2(来自评论)

  • 45

    我基本上跟着this answer,但我不想让我的"outside"代码知道关于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添加一个定义来扩展window对象 . 我把它放在typings.d.ts中:

    interface Window { my: any; }
    

    现在,从控制台调用该函数非常简单:

    my.namespace.publicFunc()
    
  • 0

    以下是一个解决方案 .

    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

    不使用全局变量的另一种方法是使用传递控制对象并将其属性绑定到要公开的变量和方法 .

    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>
    
  • 6

    当使用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();

相关问题