proyecto crear componente component comandos cli angular typescript skyscanner

crear - Cargue dinĂ¡micamente un archivo javascript externo desde un componente angular



crear proyecto angular 6 (9)

He hecho este fragmento de código

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

Y luego llámalo así

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

EDITAR: con el nuevo renderizador Api se puede escribir así

constructor(private renderer: Renderer2){} addJsToElement(src: string): HTMLScriptElement { const script = document.createElement(''script''); script.type = ''text/javascript''; script.src = src; this.renderer.appendChild(document.body, script); return script; }

StackBlitz

Estoy creando una aplicación Angular usando Angular 4 y la CLI. Estoy tratando de agregar el widget de búsqueda SkyScanner en uno de mis componentes.

Ejemplo de widget de Skyscanner

Parte de la implementación requiere la adición de un nuevo script externo:

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

No estoy seguro de la forma correcta de hacer referencia a este archivo. Si agrego el script a mi archivo index.html, el widget no se carga a menos que se realice una actualización completa de la página. Supongo que el script intenta manipular el DOM en la carga y los elementos no existen cuando se ejecuta el script.

¿Cuál es la forma correcta de cargar el script solo cuando se carga el componente que contiene el widget Skyscanner?


Intente cargar JavaScript externo en la carga de componentes de la siguiente manera:

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


La respuesta aceptada es correcta, pero no funcionará porque el navegador tarda un poco más en analizar el script después de descargarlo. Por lo tanto, si se usa alguna variable del script cargado, entonces debe usarse en el evento de carga del elemento de script html recién creado. He mejorado la respuesta aceptada como se menciona a continuación:

loadAPI: Promise<any>; constructor() { this.loadAPI = new Promise((resolve) => { let node = this.loadScript(); if (node) { node.onload = () => { resolve(true); }; } else { resolve(true); } }); } ngOnInit() { this.loadAPI .then((flag) => { //Do something when script is loaded and parsed by browser }); } loadScript() { let node = undefined; let isFound = false; const scripts = document.getElementsByTagName(''script'') for (let i = 0; i < scripts.length; ++i) { // Check if script is already there in html if (scripts[i].getAttribute(''src'') != null && scripts[i].getAttribute(''src'').includes("loader")) { isFound = true; } } if (!isFound) { const dynamicScript = ''https://widgets.skyscanner.net/widget-server/js/loader.js''; node = document.createElement(''script''); node.src = dynamicScript; node.type = ''text/javascript''; node.async = false; node.charset = ''utf-8''; document.getElementsByTagName(''head'')[0].appendChild(node); return node; } return node; }


Nota: ¡Esto es especialmente para enlaces js externos! Paso 1. ¡Se recomienda agregar su script angular al archivo index.html en la parte inferior de su cuerpo! Intenté todas las otras formas pero fallé.

<!-- File Name: index.html and its inside src dir--> <body class=""> <app-root></app-root> <!-- Icons --> <script src="https://unpkg.com/feather-icons/dist/feather.min.js"></script> </body>

A continuación, hay dos formas de hacer esto ... En Anguar5, use dentro de la carpeta de componentes en la parte superior de este código

declare var feather:any;

y luego dentro de tu clase llama al método que necesitas. Por ejemplo

//FileName: dashboard.component.ts import { Component, OnInit } from ''@angular/core''; declare var feather:any; export class DashboardComponent implements OnInit{ ngOnInit(){ feather.replace(); } }

¡y esto debería ejecutar tu código! La otra forma que podría funcionar en la versión anterior. No he comprobado!

//FileName: dashboard.component.ts import { Component, OnInit } from ''@angular/core''; export class DashboardComponent implements OnInit{ ngOnInit(){ let node = document.createElement(''script''); node.innerText=''feather.replace()''; node.type = ''text/javascript''; node.async = false; node.charset = ''utf-8''; document.getElementsByTagName(''body'')[0].appendChild(node); } }

Si no está recibiendo mi código, pruebe también este link .

¡Espero que esto ayude!


Puede crear su propia directiva para cargar el script de la siguiente manera

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

Y puede usarlo en cualquier lugar de su plantilla de componentes como se muestra a continuación

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

Por ejemplo, para cargar dinámicamente JQuery en su componente, inserte el siguiente código en la plantilla de su componente

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


Puedes hacer una cosa

si tienes angular-cli.json

entonces puedes declarar al script

me gusta

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

Y luego declara skyscanner en tu componente

me gusta

declare var skyscanner:any;

¡Eso es!

Espero que esto te ayude


Tuve el mismo problema, pero en mi caso, estaba importando 10 bibliotecas al final del archivo html, y estas bibliotecas tienen muchos métodos, escuchas, eventos y más, y en mi caso no necesitaba llame a un método específicamente.

El ejemplo sobre lo que tenía:

<!-- app.component.html --> <div> ... </div> <script src="http://www.some-library.com/library.js"> <script src="../assets/js/my-library.js"> <!-- a route in my angular project -->

Como se mencionó, no funcionó. Entonces, encuentro algo que me ayudó: la respuesta de Milad

  1. Elimine las llamadas de script en app.component.html. Debe vincular estos scripts en el archivo app.component.ts.

  2. En ngOnInit (), use un método para agregar las bibliotecas, por ejemplo:

``

<!-- app.component.ts --> export class AppComponent implements OnInit { title = ''app''; ngOnInit() { this.loadScript(''http://www.some-library.com/library.js''); this.loadScript(''../assets/js/my-library.js''); } } public loadScript(url: string) { const body = <HTMLDivElement> document.body; const script = document.createElement(''script''); script.innerHTML = ''''; script.src = url; script.async = false; script.defer = true; body.appendChild(script); } }

Funciona para mi. Yo uso Angular 6, espero que ayude.


Un poco tarde, pero prefiero hacerlo de esta manera (servicio) ...

import { Injectable } from ''@angular/core''; import { Observable } from "rxjs"; interface Scripts { name: string; src: string; } export const ScriptStore: Scripts[] = [ { name: ''script-a'', src: ''assets/js/a.js'' }, { name: ''script-b'', src: ''assets/js/b.js'' }, { name: ''script-c'', src: ''assets/js/c.js'' } ]; declare var document: any; @Injectable() export class FileInjectorService { private scripts: any = {}; constructor() { ScriptStore.forEach((script: any) => { this.scripts[script.name] = { loaded: false, src: script.src }; }); } loadJS(...scripts: string[]) { const promises: any[] = []; scripts.forEach((script) => promises.push(this.loadJSFile(script))); return Promise.all(promises); } loadJSFile(name: string) { return new Promise((resolve, reject) => { if (!this.scripts[name].loaded) { let script = document.createElement(''script''); script.type = ''text/javascript''; script.src = this.scripts[name].src; if (script.readyState) { 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 { 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'' }); } }); } }

Luego, en mi componente, podría hacer algo como:

ngOnInit() { this.fileInjectorService.loadJS(''script-a'', ''script-c'').then(data => { // Loaded A and C.... }).catch(error => console.log(error)); }

Probado en Angular 6/7


agregue loader.js a su carpeta de activos y luego en su angular-cli.json

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

luego agregue esto a sus typings.d.ts

declare var skyscanner:any;

y podrás usarlo

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