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
Ответы
Ответ 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>