javascript - etiqueta de script en plantilla/gancho angular2 cuando se carga la plantilla dom
jquery (2)
Estoy bastante atrapado y no sé cómo resolver mi problema ...
Simplificado: tengo un componente que crea una ulist basada en un enlace, como este:
@Component({
selector: "template",
template: `
<ul>
<li *ng-for="#challenge of jobs.challenges">{{challenge}}</li>
</ul>
`})
export class JobTemplate{
jobs: Jobs;
constructor(jobs:Jobs){
this.jobs = jobs
}
}
El selector / host de componentes está incrustado en el flujo html normal reflejado por php y se usa para reemplazar una ulist predefinida. El problema es que en el sitio normal, se utilizó una etiqueta de secuencia de comandos después de la ulist para aplicar algo de magia jquery en la lista.
Dado que la etiqueta del script se repite antes de que la plantilla de mi componente haya terminado de cargarse, las llamadas jquery no encontrarán los elementos de mi plantilla DOM. Poner la etiqueta de script dentro de mi plantilla (al final) no funciona; simplemente parece ser ignorado.
<ul>
<a><li *ng-for="#challenge of jobs.challenges">{{challenge}}</li></a>
</ul>
<script>
$("ul a").on("click", function (event)
{
var parent = $(this).parent();
if(parent.hasClass(''active''))
....slideToggle("normal");
else
....
});
</script>
Además, el sitio utiliza el marco de la fundación, y cada vez que se agrega un nuevo elemento a la página (por ejemplo, a través de la actualización externa de mi componente) necesito llamar a
$(document).foundation()
.
Entonces mi pregunta es, ¿cómo puedo lograr llamar a jquery en mi plantilla DOM, cuando no sé si mi plantilla ha terminado de crearse? El controlador de carga tampoco funciona cuando se define en mi plantilla de componente.
He leído sobre AfterViewInit, pero estoy un poco abrumado con eso. ¿Podría alguien empujarme en la dirección correcta?
¿Cómo puedo saber cuándo la plantilla de mi componente se ha insertado completamente en el DOM "principal"?
Encontré el mismo problema, pero además tuve que cargar varios scripts, algunos de los cuales podían cargarse en paralelo y otros en serie. Esta solución funcionará si está utilizando TypeScript 2.1 o superior , que tiene soporte nativo para async/await y se transpila a ES3 / ES5:
async ngAfterViewInit() {
await this.loadScript("http://sub.domain.tld/first-script.js")
await this.loadScript("http://sub.domain.tld/second-script.js")
}
private loadScript(scriptUrl: string) {
return new Promise((resolve, reject) => {
const scriptElement = document.createElement(''script'')
scriptElement.src = scriptUrl
scriptElement.onload = resolve
document.body.appendChild(scriptElement)
})
}
Para cualquier script que se pueda cargar en paralelo, puede aprovechar Promise.all :
async ngAfterViewInit() {
await Promise.all([
this.loadScript("http://sub.domain.tld/first-parallel.js"),
this.loadScript("http://sub.domain.tld/second-parallel.js")
])
await this.loadScript("http://sub.domain.tld/after-parallel.js")
}
Nota:
para el rechazo de la promesa, puede intentar trabajar con
scriptElement.onerror = reject
en la función
loadScript()
, sin embargo, encontré un comportamiento peculiar en esta situación.
Si desea que la secuencia de comandos siga cargándose, pase lo que pase, puede experimentar resolviendo promesas cuando se llama a onerror.
Se eliminan las etiquetas de script en las plantillas de componentes.
Una solución alternativa es crear la etiqueta del script dinámicamente en
ngAfterViewInit()
Ver también https://github.com/angular/angular/issues/4903
constructor(private elementRef:ElementRef) {};
ngAfterViewInit() {
var s = document.createElement("script");
s.type = "text/javascript";
s.src = "http://somedomain.com/somescript";
this.elementRef.nativeElement.appendChild(s);
}
Ver también https://.com/a/9413803/217408
Una mejor manera podría ser usar
require()
para cargar el script.
Consulte también la etiqueta de script en plantilla / gancho angular2 cuando se carga la plantilla dom