Подтвердить что ты не робот

Angular2 - как вызвать функцию компонента извне приложения

Я использую javascript Object, который имеет обратный вызов. Я хочу, чтобы обратный вызов был вызван для вызова функции внутри компонента 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");
}

Как я могу вызвать функцию runThisFunctionFromOutside, которая находится внутри App.component.ts

4b9b3361

Ответ 1

См. также Как публиковать angular 2 метода?

Когда компонент сконструирован, он присваивает себе глобальную переменную. Затем вы можете ссылаться на него и называть методы. Не забудьте использовать 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;
}

Пример плунжера1

В консоли браузера вы должны переключиться с <topframe> на plunkerPreviewTarget...., потому что Plunker выполняет код в iFrame. Затем запустите

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

или

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

Альтернативный подход

будет отправлять события за пределами angular и слушать их в angular, как описано в Angular 2 - передача функций typescript с внешними js-библиотеками

Пример Plunker2 (из комментариев)

Ответ 2

Я в основном соблюдал этот ответ, но я не хотел, чтобы мой "внешний" код знал что-нибудь о 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, чтобы расширить объект окна. Я положил это в typings.d.ts:

interface Window { my: any; }

Вызов функции с консоли теперь прост как:

my.namespace.publicFunc()

Ответ 3

Ниже приведено решение.

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

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");
    }
}

Ответ 4

Другим подходом, не использующим глобальные переменные, является использование объекта управления и привязка его свойств к переменным и методам, которые выставляются.

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>