How can we call angular functions using inline javascript in angular 4

In Angular 1.x, we can use angular.element(appElement).scope()

to get $scope

and then use $apply()

so native javascript can directly call Angular functions or two-way binding. Whereas with Angular 4, how can we call Angular functions or two-way binding using inline javascript or android native.

For example:

The web is developed by Angular 4 and it will be used in android web browser, so it needs android interaction, how can I handle the interaction?

+3


source to share


1 answer


I can think of many ways, but have never read anything in manuals that clarify as far as Angular itself is concerned.

Zones

You should remember that Angular uses zones and change detection tree at the core of this engine. Therefore, any external access must occur in this context.

You need to run external code in Angular zone:

zone.run(() => {
      // do work here
});

      

If you make changes to any data that directly or indirectly affects the expression of the template, you risk a change detection error. Therefore, the component must be entered ChangeDetectorRef

and called markForCheck

.

So, if the code is executed inside the component, but outside Angular. You need to do this:

zone.run(() => {
    // do work here.
    this.ChangeDetectorRef.markForCheck();
});

      

However, this raises the question. How do I get to the component?

Accessing Angular

You need to download your Angular app for it to be available.



When your Angular app loads, the browser service returns a promise to the main module. This main module contains the injector and from there you can access any exported services.

platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .then((modRef: NgModuleRef<AppModule>) => {
         window.myGlobalService = modRef.injector.get(MyServiceClass);
    });

      

This will make the service class global. You will need to create an API that goes into Angular zones.

@Injectable()
export class MyServiceClass {
     public dataEmitter: Subject<any> = new Subject();

     public constructor(private zone: NgZone) {}

     public fooBar(data: any): any {
         return this.zone.run(()=>{
             // do work here
             this.dataEmitter.next(data);
             return "My response";
         });
     }
}

      

You can return the result from zone.run

from the service. The key is that Angular code runs in the correct zone.

Simple one-way connection

The simplest solution for one way data binding is to just use the Event DOM module.

@Component({....})
export class MyComponent {
    @HostListener('example',['$event'])
    public onExample(event: Event) {
        console.log(event.fooBar);
    }
}

// else where in external JavaScript
var elem; // the DOM element with the component
var event = new Event('example', {fooBar: 'Hello from JS!'});
elem.dispatchEvent(elem);

      

I prefer this approach since Angular handles the event listener like any other kind of event (i.e. click events)

You can also do it the other way around. Have the component emit DOM events on it ElementRef

for external JavaScript to listen to. This makes all two-way communication more standard DOM.

+2


source







All Articles