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

Как публиковать angular 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.

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

вот как я это сделал. Компонент ниже. Не забудьте импортировать NgZone.it - ​​это самая важная часть здесь. NgZone, которая позволяет angular понимать внешний внешний контекст. Возможности функции через zone.run позволяют вы должны повторно войти в зону angular из задачи, которая была выполнена вне зоны angular. Нам это нужно здесь, поскольку мы имеем дело с внешним вызовом, который не находится в зоне 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');
        }
    }

теперь позволяет вызывать это извне. В моем случае я хотел бы получить здесь через теги script моего 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);});

право является лишь некоторым значением, которое передается здесь как параметр.

Ответ 3

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

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

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

Ответ 4

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

В конструкторе компонента выполните следующее:

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

И в корневом каталоге script попробуйте следующее:

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

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