0

I'm trying to implement an angular2 app that has a dependency on a 3rd party js library, that is getting included in index.html script tag. Trying to implement the sales force external identity solution as outlined here.

this script is looking for some meta tags in the page in order to function properly, whether to pop-up as a model or inline form for example.

I'm using the angular platform browser's Meta functionality to set the meta tags in the page, implemented in the constructor of app.component.ts.

This seems to have created a race condition, as in certain situations (typically, when the script exists in the browser cache) it throws alerts that the required meta tags aren't available.

How can I stop the loading of the script in index.html (I've set it with the defer and async keywords btw) to not load until AFTER the app.component has set the meta tags?

app.component.ts

import {Component, OnInit} from '@angular/core';
import {TodoService} from './providers/todo.service';
import {Meta} from '@angular/platform-browser';
import {environment} from '../environments/environment';
import { isNull } from 'util';


declare var SFIDWidget: any;
declare var SFIDWidget_loginHandler: any;
declare var SFIDWidget_logoutHandler: any;


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [TodoService]
})
export class AppComponent implements OnInit {

  constructor(public meta: Meta) {

    //meta tag stuff

    //check for meta tags and add if not exists
    if (isNull(this.meta.getTag('name="salesforce-logout-handler"'))) {
      this.meta.addTags(
        [
          {
            name: "salesforce-client-id",
            content: `${environment.clientId}`
          },
          {
            name: "salesforce-community",
            content: `${environment.communityURL}`
          },
          {
            name: "salesforce-redirect-uri",
            content: `${environment.redirectURL}`
          },
          {
            name: "salesforce-mode",
            content: "modal"
          },
          {
            name: "salesforce-forgot-password-enabled",
            content: "true"
          },
          {
            name: "self-register-enabled",
            content: "true"
          },
          {
            name: "salesforce-save-access-token",
            content: "true"
          },
          {
            name: "salesforce-target",
            content: "#salesforce-login"
          },
          {
            name: "salesforce-login-handler",
            content: "onLogin"
          },
          {
            name: "salesforce-logout-handler",
            content: "onLogout"
          }
        ], true);
    } else {

      console.log('meta tags exist!');
    }


  }

  ngOnInit() {


  }

  onLogin(identity) {

    console.log('fired from the app component');

  }


  onLogout() {

    SFIDWidget.init();
  }


}

index.html

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Herokudos</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <script
    src="https://sdo-134f326f986sdo-134f326f986.force.com/servlet/servlet.loginwidgetcontroller?type=javascript_widget&min=false&cacheMaxAge=0"
    async defer></script>
  <link
    href="https://sdo-134f326f986sdo-134f326f986.force.com/servlet/servlet.loginwidgetcontroller?type=css"
    rel="stylesheet" type="text/css"/>
</head>
<body>
<app-root>Loading...</app-root>

</body>
</html>
2
  • If you have the control on the index.html file you can change the script type to something that browser won't execute like type="text/don't-execute", and change it to text/javascript or just remove it when you're done modifying Meta tags. This is brute force of course, in case you can't find anything built in for Angular Commented Jun 25, 2017 at 1:51
  • refer to this answer for loading scripts at runtime stackoverflow.com/questions/34489916/… Commented Oct 31, 2017 at 15:29

1 Answer 1

3

Remove the <script> tag that you hardcoded into index.html. If you want to load scripts that depend on Angular being ready, consider loading them dynamically in the component's ngAfterViewInit() lifecycle hook. This will guarantee that the script will load only after your AppComponent has been rendered.

AppComponent

/*executes once the component template is built*/
ngAfterViewInit(){
    //Add a script tag to the DOM
    let script = document.createElement('script');
    document.body.appendChild(script);

    //listen for the load event on the script...
    Observable.fromEvent(script,'load').first().subscribe(
          //...and call onScriptLoad once the script is loaded
          ()=>this.onScriptLoad()
    );

    //set script source: will trigger the download
    script.src = "https://sdo...";
}

/*executes once the script has been loaded*/
onScriptLoad(){}
Sign up to request clarification or add additional context in comments.

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.