Как публично выставить угловые 2 метода?

В настоящее время я работаю над переносом проекта Backbone на проект Angular 2 (очевидно, с большим количеством изменений), и одно из требований проекта требует, чтобы определенные методы были доступны публично.

Быстрый пример:

Составная часть

@component({...})
class MyTest {
    private text:string = '';
    public setText(text:string) {
        this.text = text;
    }
}

Очевидно, я мог бы <button (click)="setText('hello world')>Click me!</button>и я бы тоже хотел это сделать. Тем не менее, я хотел бы иметь доступ к нему публично.

Как это

<button onclick="angular.MyTest.setText('Hello from outside angular!')"></click>

Или это

// in the js console
angular.MyTest.setText('Hello from outside angular!');

В любом случае, я бы хотел, чтобы этот метод был публично представлен, чтобы его можно было вызывать из приложения angular 2.

Это то, что мы сделали в магистральной сети, но я думаю, что мой Google foo недостаточно силен, чтобы найти хорошее решение для этого, используя angular.

Мы бы предпочли использовать только некоторые методы и иметь список общедоступных API-адресов, так что если у вас есть советы, как это сделать, это будет дополнительным бонусом. (У меня есть идеи, но другие приветствуются.)

4 ответа

Решение

Просто сделайте так, чтобы компонент регистрировался в глобальной карте, и вы можете получить к нему доступ оттуда

Используйте либо конструктор, либо ngOnInit() или любой из других хуков жизненного цикла для регистрации компонента и ngOnDestroy() отменить регистрацию.

Когда вы вызываете Angular-методы извне Angular, Angular не распознает изменение модели. Это то, что Angulars NgZone для. Чтобы получить ссылку на угловую зону, просто введите ее в конструктор

constructor(zone:NgZone) {
}

Вы можете сделать zone также доступны в глобальном объекте или просто выполняют код внутри компонента в пределах зоны.

Например

calledFromOutside(newValue:String) {
  this.zone.run(() => {
    this.value = newValue;
  });
}

или используйте ссылку глобальной зоны, как

zone.run(() => { component.calledFromOutside(newValue); });

https://plnkr.co/edit/6gv2MbT4yzUhVUfv5u1b?p=preview

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

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

или же

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

Вот как я это сделал. Мой компонент приведен ниже. Не забудьте импортировать NgZone. Это самая важная часть здесь. Это NgZone, который позволяет angular понимать вне внешнего контекста. Запуск функций через зону позволяет повторно войти в угловую зону из задачи, которая была выполнена за пределами угловой зоны. Нам это нужно здесь, так как мы имеем дело с внешним вызовом, который не находится в угловой зоне.

 import { Component, Input , NgZone } from '@angular/core';
 import { Router } from '@angular/router';

    @Component({
        selector: 'example',
        templateUrl: './example.html',
    })
    export class ExampleComponent {
            public constructor(private zone: NgZone, private router: Router) {

//exposing component to the outside here
//componentFn called from outside and it in return calls callExampleFunction()
        window['angularComponentReference'] = {
            zone: this.zone,
            componentFn: (value) => this.callExampleFunction(value),
            component: this,
        };
    }

    public callExampleFunction(value: any): any {
        console.log('this works perfect');
        }
    }

Теперь давайте вызовем это извне. В моем случае, я хотел бы получить доступ к нему через теги сценария моего index.html.my index.html, приведенного ниже.

<script>

//my listener to outside clicks
ipc.on('send-click-to-AT', (evt, entitlement) => 
electronClick(entitlement));;

//function invoked upon the outside click event

 function electronClick(entitlement){
//this is the important part.call the exposed function inside angular 
//component

    window.angularComponentReference.zone.run(() =
    {window.angularComponentReference.componentFn(entitlement);});
 }
</script>

если вы просто наберете ниже в консоли разработчика и нажмете Enter, он вызовет открытый метод, и "это работает отлично" будет напечатано на консоли.

 window.angularComponentReference.zone.run(() =>
{window.angularComponentReference.componentFn(1);});

Право это просто какое-то значение, которое передается здесь в качестве параметра.

Я проверял код и столкнулся с тем, что Зона, вероятно, не нужна. Хорошо работает без NgZone.

В конструкторе компонентов сделайте это:

constructor(....) {
   window['fncIdentifierCompRef'] = {
      component  = this
   };
}

И в корневом скрипте попробуйте это:

<script>
function theGlobalJavascriptFnc(value) {
  try {
    if (!window.fncIdentifierCompRef) {
      alert('No window.fncIdentifierCompRef);
      return;
    }
    if (!window.fncIdentifierCompRef.component) {
      alert('No window.fncIdentifierCompRef.component');
      return;
    }  
    window.fncIdentifierCompRef.component.PublicCmpFunc(value);
  } catch(ex) {alert('Error on Cmp.PublicCmpFunc Method Call')}  
}
</script>

Это работает для меня.

Проблема в том, что компоненты Angular переносятся в модули, к которым не так легко получить доступ, как в обычном коде JavaScript. Процесс доступа к функциям модуля зависит от формата модуля.

Класс Angular2 может содержать статические члены, которые могут быть определены без создания нового объекта. Возможно, вы захотите изменить свой код на что-то вроде:

@component({...})
class MyTest {
    private static text: string = '';
    public static setText(text:string) {
        this.text = text;
    }
}

Супер простое решение!! сохранить компонент или функцию с псевдонимом вне

declare var exposedFunction;
@Component({
  templateUrl: 'app.html'
})
export class MyApp {
    constructor(public service:MyService){
    exposedFunction = service.myFunction;
}

в index.html добавить в голову

<script>
    var exposedFunction;
</script>

Внутри выставленной функции не используйте это. параметры, если они вам нужны, вам придется использовать замыкания, чтобы заставить его работать

Это особенно полезно в Ionic для тестирования уведомлений устройства в Интернете, а не устройства

Другие вопросы по тегам