How to expose angular 2 methods publicly?

前端 未结 5 1352
再見小時候
再見小時候 2020-11-28 09:40

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

相关标签:
5条回答
  • 2020-11-28 09:48

    Super simple solution!! save component or function with an alias outside

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

    at index.html add in head

    <script>
        var exposedFunction;
    </script>
    

    Inside exposed function do not use this. parameters if you need them you will have to use closures to get it to work

    This is particularly useful in ionic to test device notifications on web instead of device

    0 讨论(0)
  • 2020-11-28 09:59

    This is how i did it. My component is given below. Don't forget to import NgZone. It is the most important part here. It's NgZone that lets angular understand outside external context. Running functions via zone allows you to reenter Angular zone from a task that was executed outside of the Angular zone. We need it here since we are dealing with an outside call that's not in angular zone.

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

    now lets call this from outside.in my case i wanted to reach here through the script tags of my index.html.my index.html is given below.

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

    if you just type the below in developer console and hit enter it will invoke the exposed method and 'this works perfect ' will be printed on console.

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

    entitlement is just some value that is passed here as a parameter.

    0 讨论(0)
  • 2020-11-28 10:02

    I was checking the code, and I have faced that the Zone is not probably necessary. It works well without the NgZone.

    In component constructor do this:

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

    And in the root script try 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>
    

    This works to me.

    0 讨论(0)
  • 2020-11-28 10:11

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-28 10:14

    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');})
    
    0 讨论(0)
提交回复
热议问题