2

I have the following scenario.

I have a simple angular 2 app with a service which I add to providers in app.module. When I click on a button the app should load a javascript file and execute a function e.g function A defined in this javascript file. So the question is how can I access the service within this function A. My consideration is to append the service to the global window variable. Are there better ways to achieve it?

Code:

export class MyService{
    public editProjectDone = new Subject<string>();
}

app.module.ts
{
    ...providers: [MyService]
}

app.component.html
<button (click)="editProject()">Edit project</button>

app.component.ts
function editProject(){
    ... load Javascript file
    call javascript file
    js.editProject("projectId") // call function defined in javascript file
}

javascript file
{
    function editProject(projectId)
    {
        //do calculation 
        // fire event that calculation is done
        // the calcuation is not done in typescript, but here
        MyService.editProjectDone.next() 
        // The question is here how to access the event and fire it
    }
}
6
  • Not cleared about the Javascript file???? You mean typescript??? Commented Sep 11, 2018 at 5:27
  • Hi Raj, you can load external javascript file in angular 2 application and execute function defined in it. Commented Sep 11, 2018 at 5:35
  • are you trying to call a js in angular ?? Commented Sep 11, 2018 at 5:37
  • yes, i know how to call the js function in angular, but i want to access the service ( provider) of angular application Commented Sep 11, 2018 at 5:39
  • Sorry, I have not tried this Commented Sep 11, 2018 at 5:39

4 Answers 4

4

So you want to access angular service method in javascript function A().

For example:

Your service class:

export class SettingsService{
    getLanguage() {
        return 'en-GB';
    }
}

Your javascript file

function A() {
    settingsService.getLanguage();
}

Solution: Custom Event.

Basically you define a custom event handler in javascript file. And define the Custom Event and dispatchEvent the Custom Event in Angular click event function.

app.component.html:

<input type="button" value='log' (click)="logclick($event)">

app.component.ts

constructor(private settings: SettingsService){}

logclick(event){
    // define custom event
    var customevent = new CustomEvent(
    "newMessage", 
    {
        detail: {
            message: "Hello World!",
            time: new Date(),
            myservice: this.settings //passing SettingsService reference
        },
        bubbles: true,
        cancelable: true
      }
    );
    event.target.dispatchEvent(customevent); //dispatch custom event
}

javascript file:

// event handler function
function newMessageHandler(e) {
    console.log(
        "Event subscriber on "+e.currentTarget.nodeName+", "
        +e.detail.time.toLocaleString()+": "+e.detail.message
    );
    //calling SettingsService.getLanguage()
    console.log(e.detail.myservice.getLanguage());
}
//adding listener to custom event.
document.addEventListener("newMessage", newMessageHandler, false);

Example output:

Event subscriber on #document, 9/11/2018, 11:31:36 AM: Hello World!
en-GB

Note: I have not added section for dynamically loading javascript file. I assume you are already able to do that from your comments.

Sign up to request clarification or add additional context in comments.

4 Comments

HI j4rey. Your answer seems to be correct for this case. I have another scenario when i load external html file and render it by setting innerHtml. In that external html is a button. When i click on the button a javascript function will be called. In that function i want to access the service of the angular app. How can it be achieved in this case? If the question is not clear. I will create another question with code.
AngularChan as j4rey said, i agree that the better solution for this one is with custom events rather than global variable. for this scenario also you can send custom event from btn click function which your angular service is listening on this event, when ever your listener in angular service received this event, create another custom event like @j4rey said and the rest will be like as j4rey code. hope it help.
I understood your scenario, however I have two questions. 1) How are you loading and setting external html, from angular or from javascript? 2) Where is the click function defined? Is it possible to define that in ts file itself?
I get the html template string by http.get request and set the innerHtml of the angular component like <div [innerHTML]="theHtmlString"></div>. I know the paths of the external javascript file and load it by $.getScript. When i click on the button of the html template the function in the javascript should be called. So the scenario is the html template and the javascript content are unknown to angular. But the javascript function should be able to call the service from angular application.
2

Declare variable as public using window object but in proper way. export only some functions not whole service and in some standard way like below.

In Angular

export class AbcService {
  constructor() {
    const exportFunctions = {
      xyzFunction: this.xyzFunction.bind(this),
      pqrFunction: this.pqrFunction.bind(this)
    }; // must use .bind(this)
    window['ngLib']['abcService'] = exportFunctions;
  }

  xyzFunction(param1, param2) {
    // code
  }

  pqrFunction() {
    // code
  }

  private oneFunction() {
    // code
  }

  private twoFunction() {
    // code
  }
}

In Javascript

ngLib.abcService.xyzFunction(value1, value2);
ngLib.abcService.pqrFunction();

Comments

0

Firstly you need to import the js file before calling the service and that can be done by:

TS

let js: any = require('JSFileNAME')['default']; //Something lik this in constructer

then once the file is imported you need to create a instantiate of the js in your Ts something like

this.newObjectOfJs = new js(); // pass any paramater if its required.

hereafter you will be able to access the methods and service from the JSfile.

3 Comments

Hi, i wanna achieve the opposite. Call the service of angular 2 app from javascript function.
need to understand your code and project structure. any code would be helpful.
yeah. I just added some code to make my question clearer.
-1

You have to use service variable to access functions and variable of particular services.

Here I demonstrate how you can do it.

export class AppComponent  {
  name = 'Angular';
  constructor(private myServices: MyServices){
     this.myServices.sayHello();
  }
}

Whole code available here : https://stackblitz.com/edit/angular-services-example

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.