2016-02-08 10 views
15

Obecnie pracuję nad przeniesieniem projektu szkieletu do projektu Angular 2 (oczywiście z wieloma zmianami), a jedno z wymagań projektu wymaga, aby pewne metody były dostępne publicznie.Jak publicznie udostępnić metody kątowe 2?

Szybki przykład:

Komponent

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

Oczywiście, mógłbym <button (click)="setText('hello world')>Click me!</button>, i chciałbym to zrobić również. Chciałbym jednak móc uzyskać do niego dostęp publicznie.

Ci się to

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

Albo ten

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

Tak czy inaczej, chciałbym metoda być publicznie wystawiony tak to można nazwać spoza kątowej 2 app.

To jest coś, co zrobiliśmy w kręgosłupie, ale myślę, że mój Google foo nie jest wystarczająco silny, aby znaleźć dobre rozwiązanie do tego przy użyciu kątowego.

Wolelibyśmy ujawnić tylko niektóre metody i mieć listę publicznych apisów, więc jeśli masz wskazówki, jak to zrobić, byłby to dodatkowy bonus. (Mam pomysły, ale inne są mile widziane.)

+0

Możliwy duplikat [Angular2 - jak wywołać funkcję komponentu spoza aplikacji] (http://stackoverflow.com/questions/35296704/angular2-how-to-call-function-function-from-outside-the- app) –

+1

@DaveKennedy zdajesz sobie sprawę, że to pytanie zostało wysłane wcześniej, prawda? – Jacques

Odpowiedz

17

Wystarczy, że sam komponent zarejestruje się w globalnej mapie i będziesz mógł uzyskać do niego dostęp.

Użyj konstruktora lub ngOnInit() lub jednego z pozostałych lifecycle hooks, aby zarejestrować komponent i ngOnDestroy(), aby go wyrejestrować.

Po wywołaniu metod kątowych spoza kątowego, Angular nie rozpoznaje zmiany modelu. Właśnie do tego służy Angulars NgZone. Aby uzyskać odniesienie do strefy Kątowymi prostu wstrzyknąć go do konstruktora

constructor(zone:NgZone) { 
} 

Można odbyć zone sama dostępne w globalnej obiektu, jak również, czy tylko wykonanie kodu wewnątrz elementu w obrębie strefy.

Na przykład

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

lub wykorzystać globalną odniesienie strefy jak

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

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

W konsoli przeglądarki trzeba przełączyć z <topframe> do plunkerPreviewTarget.... ponieważ Plunker wykonuje kod w iFrame.Następnie uruchom

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

lub

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

Ok, więc będę potrzebować metod pomocniczych dla wszystkich moich publicznych metod. Wielkie dzięki za pomoc, przy okazji. – Jacques

+0

Tak więc, tworząc usługę, która rejestruje zadania, mam taki sam problem jak przed rozpoczęciem korzystania z 'zone.run (() => {}). Metoda jest zarejestrowana i mogę ją nazwać bez problemu wydaje się jednak, że wykrywanie zmian nie jest uruchamiane. 'window.widget [nazwa] =() => { window.zone.run (() => { scope [callbackMethod](); }); }; ' ' scope' powyżej to komponent, a metoda, którą wywołuję, to 'callbackMethod'. Jakieś wskazówki? – Jacques

+0

Doceniam plunkr, ale problem polega na tym, że mam zewnętrzną usługę, która dodaje metodę do obiektu window.widget. Mogę wywoływać metody, ale wykrywanie zmian nie jest wyzwalane.Wygląda na to, że Twój przykład zawiera to, czego używałem, gdy nie korzystałem z usługi zewnętrznej. (Mogę po prostu zrzucić tę zewnętrzną usługę.) Dzięki za pomoc. – Jacques

1

Problem polega na tym, że składniki kątowej są transpiled na moduły, które nie są tak łatwo dostępne jak regularne kodu JavaScript. Proces dostępu do funkcji modułu zależy od formatu modułu.

Klasa Angular2 może zawierać statyczne elementy, które można zdefiniować bez tworzenia instancji nowego obiektu. Może chcesz zmienić swój kod do czegoś podobnego:

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

Czy nadal nie potrzebuję sposobu publicznego ujawnienia tego elementu? – Jacques

+0

Aby uzyskać dostęp do komponentu spoza Angular, należy przejrzeć transpiled JavaScript. Ogólnie strony internetowe ładują komponenty, uzyskując dostęp do programu ładującego (zobacz 'System.import' w [SystemJS] (https://github.com/systemjs/systemjs)). – MatthewScarpino

+0

Komponenty załadowane przez systemjs są domyślnie niedostępne, patrząc na transpsynowane js nie pomagają, ponieważ js ładuje za pomocą system.register. Kątowa (lub kanciasta, itp.) Nie jest nawet dostępna w zasięgu globalnym, (http://stackoverflow.com/questions/34779126/detect-whether-angular2-is-loaded-on-a-page-when-using-systemjs) i nie będziemy używać programu systemjs w produkcji. – Jacques

3

ten sposób zrobiłem it.my składnikiem jest podana below.dont zapomnij importować NgZone.it jest najważniejsze here.its część NgZone które pozwalają kątowe do zrozumienia zewnętrznego kontekstu zewnętrznego. Przekazywanie funkcji przez zone.run umożliwia ponowne wprowadzenie strefy kątowej z zadania wykonanego poza strefą kątową. Potrzebujemy go tutaj, ponieważ mamy do czynienia z zewnętrznym wywołaniem, które nie znajduje się w strefie kątowej.

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

teraz nazwijmy to z outside.in moim przypadku chciałem dotrzeć tu przez znaczniki skryptów mojego index.html.my index.html znajduje się poniżej.

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

jeśli po prostu wpisz poniżej w konsoli programisty i wciśnij enter będzie powoływać się na odsłoniętej metodę i „działa to idealne” zostaną wydrukowane na konsoli.

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

uprawnienie to tylko pewna wartość, którą podaje się tutaj jako parametr.

+0

Po prostu podążałem twoimi krokami za pomocą 'Nie mogę odczytać właściwości 'strefy' niezdefiniowanej', która występuje w 'ClickEvent' w' home.cshtml' moja funkcja wygląda jak ' '** ps: ** W konsoli programisty działa poprawnie. – k11k2

+0

czy importowałeś Ngzone do swojego komponentu? –

0

Sprawdzałem kod, a ja stawiam czoła, że ​​Strefa nie jest prawdopodobnie konieczna. Działa dobrze bez NgZone.

W konstruktorze komponentu to zrobić:

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

I w scenariuszu głównym spróbuj tego:

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

Działa to na mnie.

Powiązane problemy