Jacques February 2016

How do expose angular 2 methods publicly?

I am currently working on porting a Backbone project to an Angular 2 project (obviously with a lot of changes), and one of the project requirements requires certain methods to be accessible publicly.

A quick example:

Component

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

Obviously, I could have <button (click)="setText('hello world')>Click me!</button>, and I would want to do that as well. However, I'd like to be able to access it publicly.

Like this

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

Or this

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

Either way, I would like the method to be publicly exposed so it can be called from outside the angular 2 app.

This is something we've done in backbone, but I guess my Google foo isn't strong enough to find a good solution for this using angular.

We would prefer to only expose some methods and have a list of public apis, so if you have tips for doing that as well, it'd be an added bonus. (I have ideas, but others are welcomed.)

Answers


Günter Zöchbauer February 2016

Just make the component register itself in a global map and you can access it from there.

Use either the constructor or ngOnInit() or any of the other lifecycle hooks to register the component and ngOnDestroy() to unregister it.

When you call Angular methods from outside Angular, Angular doesn't recognize model change. This is what Angulars NgZone is for. To get a reference to Angular zone just inject it to the constructor

constructor(zone:NgZone) {
}

You can either make zone itself available in a global object as well or just execute the code inside the component within the zone.

For example

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

or use the global zone reference like

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

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

In the browser console you have to switch from <topframe> to plunkerPreviewTarget.... because Plunker executes the code in an iFrame. Then run

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

or

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


MattScarpino February 2016

The problem is that Angular's components are transpiled into modules that aren't as easy to access as regular JavaScript code. The process of accessing a module's features depends on the module's format.

An Angular2 class can contain static members that can be defined without instantiating a new object. You might want to change your code to something like:

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

Post Status

Asked in February 2016
Viewed 1,106 times
Voted 5
Answered 2 times

Search




Leave an answer