2017-05-26 11 views
10

Tworzę aplikację Angular przy użyciu Angular 4 i CLI. Próbuję dodać widget wyszukiwania SkyScanner do jednego z moich komponentów.Dynamicznie ładuj zewnętrzny plik javascript z Angular komponentu

Skyscanner Widget Example

ramach realizacji wymaga dodania nowego skryptu zewnętrzne:

<script src="https://widgets.skyscanner.net/widget-server/js/loader.js" async></script> 

nie jestem pewny poprawnej sposób odwoływać się do tego pliku. Jeśli dodaję skrypt do mojego pliku index.html, widget nie zostanie załadowany, dopóki nie zostanie wykonane pełne odświeżenie strony. Zakładam, że skrypt próbuje manipulować DOM przy obciążeniu, a elementy nie istnieją podczas działania skryptu.

Jaki jest prawidłowy sposób ładowania skryptu tylko po załadowaniu komponentu zawierającego widget Skyscanner?

Odpowiedz

20

Try załadować skrypt na ładowanie komend, jak poniżej:

loadAPI: Promise<any>; 

constructor() {   
    this.loadAPI = new Promise((resolve) => { 
     this.loadScript(); 
     resolve(true); 
    }); 
} 

public loadScript() {   
    var isFound = false; 
    var scripts = document.getElementsByTagName("script") 
    for (var i = 0; i < scripts.length; ++i) { 
     if (scripts[i].getAttribute('src') != null && scripts[i].getAttribute('src').includes("loader")) { 
      isFound = true; 
     } 
    } 

    if (!isFound) { 
     var dynamicScripts = ["https://widgets.skyscanner.net/widget-server/js/loader.js"]; 

     for (var i = 0; i < dynamicScripts .length; i++) { 
      let node = document.createElement('script'); 
      node.src = dynamicScripts [i]; 
      node.type = 'text/javascript'; 
      node.async = false; 
      node.charset = 'utf-8'; 
      document.getElementsByTagName('head')[0].appendChild(node); 
     } 

    } 
} 
+0

To wygląda jak najlepsza odpowiedź do tej pory. Dziękuję Ci. Czy wywołanie loadScript powinno znajdować się w konstruktorze, czy byłoby lepiej w ngOnInit? – psych

+0

Nie próbowałem z ngOnInit, ale jeśli działa z INIT, to najlepsze miejsce do umieszczenia tam –

+0

, ale ładowanie tego pliku dostaje opóźnienie, więc moje funkcje są renderowane bez tej wiedzy. a później załadowany bez użycia. Jak rozwiązać ten problem. –

2

dodać loader.js do folderu swoje aktywa następnie w angular-cli.json

"scripts": ["./src/assets/loader.js",] 

następnie dodać do swojej typings.d.ts

declare var skyscanner:any; 

i będzie można z niego korzystać

skyscanner.load("snippets","2"); 
+0

Czy ostatnią linię Dodaję (skyscanner.load ...) dodać do komponentu? Zakładając, że widzę błąd mówiący, że nie mogę znaleźć nazwy skyscanner. – psych

0

Można zrobić jedną rzecz

jeśli masz skośnych cli.json

następnie można zadeklarować do skryptu

jak

"scripts": ["../src/assets/js/loader.js"] 

A potem zadeklarować w Skyscanner Twój komponent podobnie jak

declare var skyscanner:any; 

To wszystko!

Nadzieja to pomóc

+0

Dodałem skrypt lokalnie i umieściłem go w pliku kątowym-cli.json. Niestety to nie działa. Czy możesz wyjaśnić, co należy zrobić, dodając deklarację do komponentu? – psych

3

Zrobiłem ten fragment kodu

addJsToElement(src: string): HTMLScriptElement { 
    const script = document.createElement('script'); 
    script.type = 'text/javascript'; 
    script.src = src; 
    this.elementRef.nativeElement.appendChild(script); 
    return script; 
    } 

a następnie wywołać go jak ten

this.addJsToElement('https://widgets.skyscanner.net/widget-server/js/loader.js').onload =() => { 
     console.log('SkyScanner Tag loaded'); 
} 
0

Można tworzyć własne dyrektywę, aby załadować skrypt jako poniżej:

import { Directive, OnInit, Input } from '@angular/core'; 

@Directive({ 
    selector: '[appLoadScript]' 
}) 
export class LoadScriptDirective implements OnInit{ 

    @Input('script') param: any; 

    ngOnInit() { 
     let node = document.createElement('script'); 
     node.src = this.param; 
     node.type = 'text/javascript'; 
     node.async = false; 
     node.charset = 'utf-8'; 
     document.getElementsByTagName('head')[0].appendChild(node); 
    } 

} 

I można go używać w dowolnym miejscu w szablonie elementów jak poniżej

<i appLoadScript [script]="'script_file_path'"></i> 

Dla przykładu, aby załadować dynamicznie JQuery w składniku, wstawić poniżej kodu w szablonie komponentu za

<i appLoadScript [script]="'/assets/baker/js/jquery.min.js'"></i> 
Powiązane problemy