chikun
chikun

Reputation: 199

Angular 4 routers not loading components

I'm trying to build an Angular project for a construction company for which I downloaded the html template from a genuine website. Now, I'm trying to migrate the code to Angular 4. I've implemented router concept on my project to navigate to different pages.

Below is project structure -

src 
|_
   app
    |_aboutus
    |_home
    |_app_root(app.component.html)
  |_assets
  |_index.html

So I've included all my css and external js files to index.html page which is going to be used in across all components. In app.component.html I have put the nav bar below which I have

<router-outlet> </router-outlet>

tag. I have my html code in home and aboutus component. below is my app.module.ts file -

 imports: [
    BrowserModule,
    RouterModule.forRoot([
      {
         path: 'about-us',
         component: AboutusComponent
      },
      {
        path: 'home',
        component: HomeComponent
     },
     {
      path: '',
      component: HomeComponent
     }
   ])
  ]

Now if I run localhost:4200 it by default renders the view of home component. when I hit the aboutus pae it renders few texts and unable to load animations. However if I directly hit the aboutus page like this (localhost:4200/about-us) it ables to load the data. My question is what is wrong I'm doing with routing here ? For code reference - https://github.com/chikun525/RetroBuildConNew

Upvotes: 1

Views: 96

Answers (1)

K. Ayoub
K. Ayoub

Reputation: 426

You have to load your javascript files dynamically:

DynamicScriptLoaderService

import { Injectable } from '@angular/core';

interface Scripts {
  name: string;
  src: string;
}

export const ScriptStore: Scripts[] = [
  { name: 'chartjs', src: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js' },
  { name: 'random-gen', src: '../../../assets/js/random-num-generator.js' }
];

declare var document: any;

@Injectable()
export class DynamicScriptLoaderService {

  private scripts: any = {};

  constructor() {
    ScriptStore.forEach((script: any) => {
      this.scripts[script.name] = {
        loaded: false,
        src: script.src
      };
    });
  }

  load(...scripts: string[]) {
    const promises: any[] = [];
    scripts.forEach((script) => promises.push(this.loadScript(script)));
    return Promise.all(promises);
  }

  loadScript(name: string) {
    return new Promise((resolve, reject) => {
      if (!this.scripts[name].loaded) {
        //load script
        let script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = this.scripts[name].src;
        if (script.readyState) {  //IE
            script.onreadystatechange = () => {
                if (script.readyState === "loaded" || script.readyState === "complete") {
                    script.onreadystatechange = null;
                    this.scripts[name].loaded = true;
                    resolve({script: name, loaded: true, status: 'Loaded'});
                }
            };
        } else {  //Others
            script.onload = () => {
                this.scripts[name].loaded = true;
                resolve({script: name, loaded: true, status: 'Loaded'});
            };
        }
        script.onerror = (error: any) => resolve({script: name, loaded: false, status: 'Loaded'});
        document.getElementsByTagName('head')[0].appendChild(script);
      } else {
        resolve({ script: name, loaded: true, status: 'Already Loaded' });
      }
    });
  }

}

in the component.ts

// Angular
import { Component, OnInit } from '@angular/core';

// Service
import { DynamicScriptLoaderService } from '../../shared/services/dynamic-script-loader.service';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html'
})
export class DashboardComponent implements OnInit {


  constructor(private dynamicScriptLoader: DynamicScriptLoaderService) {}

  ngOnInit() {
    // Just call your load scripts function with scripts you want to load
    this.loadStripeScripts();
  }

  private loadChartScripts() {
    // You can load multiple scripts by just providing the key as argument into load method of the service
    this.dynamicScriptLoader.load('chartjs','random-num').then(data => {
      // Script Loaded Successfully
    }).catch(error => console.log(error));
  }

}

And don't forget to add the service to you app.module

providers: [
        DynamicScriptLoaderService
    ],

source: https://medium.com/@zainzafar/angular-load-external-javascript-file-dynamically-3d14dde815cb

Edit :

here's a workaround: in the Javascript file you want to execute put all the code of that file inside a function, for exemple:

function myFunction() {
    alert("hello world");
    // here's goes all the javascript code
}

in your html file of you component(AboutusComponent) put the following tag somewhere:

<button onclick="myFunction()" id="scriptCall" style="display: none"></button>

and in the ngOnInit method of your compononent (AboutusComponent) put the following code

 var scriptCall = document.getElementById('scriptCall');
 scriptCall.click();

Upvotes: 2

Related Questions