I'm pretty stuck and don't know how to solve my problem...
我被困住了,不知道如何解决我的问题……
Simplified: I have a component that creates a ulist based on a binding, like this:
简体:我有一个组件,它基于绑定创建一个ulist,如下所示:
@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
}
}
The component selector/host is embedded in normal html flow echoed by php and is used to replace a predefined ulist. The problem is that on the normal site, a script tag after the ulist was used to apply some jquery magic on the list.
组件选择器/主机被嵌入到php回显的普通html流中,用于替换预定义的ulist。问题是在正常的站点上,使用ulist后的脚本标记用于在列表中应用一些jquery魔法。
Since the script tag is echoed out before the template of my component has finished loading, the jquery calls won't find the elements of my template DOM. Putting the script tag inside my template (at the end) does not work; it simply seems to get ignored.
由于脚本标记在组件的模板完成加载之前被回显,jquery调用不会找到模板DOM的元素。将脚本标记放在模板内(最后)不起作用;它似乎被忽视了。
<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>
Also the site uses the foundation framework, and each time a new element is added to the page (e.g through the binding of my component being updated externally) I need to call $(document).foundation()
.
站点还使用foundation框架,每次向页面添加新元素时(e)。通过对我的组件进行外部更新的绑定,我需要调用$(document).foundation()。
So my question is, how can I achieve to call jquery on my template DOM, when I don't know if my template has finished being created. The onload handler doesn't work either when defined in my component template.
所以我的问题是,当我不知道模板是否已经被创建时,如何在模板DOM上调用jquery。onload处理程序在我的组件模板中定义时不起作用。
I have read about AfterViewInit, but I'm kind of overwhelmed with it. Could someone please push me in the right direction?
我读过关于AfterViewInit的文章,但我有点被它淹没了。谁能把我推到正确的方向上吗?
How can I find out when the template of my component has been fully inserted into the "main" DOM?
如何确定组件的模板何时被完全插入到“main”DOM中?
2 个解决方案
#1
21
Script tags in component templates are removed. A workaround is to create the script tag dynamically in ngAfterViewInit()
组件模板中的脚本标记被删除。一个解决方案是在ngAfterViewInit()中动态创建脚本标记
See also https://github.com/angular/angular/issues/4903
参见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);
}
See also https://*.com/a/9413803/217408
参见https://*.com/a/9413803/217408
A better way might be to just use require()
to load the script.
更好的方法可能是使用require()加载脚本。
See also script tag in angular2 template / hook when template dom is loaded
当加载模板dom时,请参见angular2模板/ hook中的脚本标记
#2
7
I encountered the same issue, but additionally I had to load in a number of scripts, some of which could loaded in parallel, and others in series. This solution will work if you are using TypeScript 2.1 or greater, which has native support for async/await and transpiles to ES3/ES5:
我遇到了同样的问题,但是另外,我必须加载许多脚本,其中一些可以并行加载,另一些可以串行加载。如果您使用的是TypeScript 2.1或更高版本,那么这个解决方案将有效,它对异步/ wait和传输到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)
})
}
For any scripts that can be loaded in parallel, you can take advantage of Promise.all:
对于任何可以并行加载的脚本,您都可以利用promise.com。
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")
}
Note: For promise rejection, you can try working with scriptElement.onerror = reject
in the loadScript()
function, however, I encountered some quirky behavior in this situation. If you want script to keep loading no matter what, you may want to experiment with resolving promises when onerror is called.
注意:对于拒绝承诺,您可以尝试使用scriptElement。不过,在loadScript()函数中,我遇到了一些奇怪的行为。如果您希望脚本无论如何都保持加载,那么您可能希望在调用onerror时尝试解析承诺。
#1
21
Script tags in component templates are removed. A workaround is to create the script tag dynamically in ngAfterViewInit()
组件模板中的脚本标记被删除。一个解决方案是在ngAfterViewInit()中动态创建脚本标记
See also https://github.com/angular/angular/issues/4903
参见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);
}
See also https://*.com/a/9413803/217408
参见https://*.com/a/9413803/217408
A better way might be to just use require()
to load the script.
更好的方法可能是使用require()加载脚本。
See also script tag in angular2 template / hook when template dom is loaded
当加载模板dom时,请参见angular2模板/ hook中的脚本标记
#2
7
I encountered the same issue, but additionally I had to load in a number of scripts, some of which could loaded in parallel, and others in series. This solution will work if you are using TypeScript 2.1 or greater, which has native support for async/await and transpiles to ES3/ES5:
我遇到了同样的问题,但是另外,我必须加载许多脚本,其中一些可以并行加载,另一些可以串行加载。如果您使用的是TypeScript 2.1或更高版本,那么这个解决方案将有效,它对异步/ wait和传输到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)
})
}
For any scripts that can be loaded in parallel, you can take advantage of Promise.all:
对于任何可以并行加载的脚本,您都可以利用promise.com。
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")
}
Note: For promise rejection, you can try working with scriptElement.onerror = reject
in the loadScript()
function, however, I encountered some quirky behavior in this situation. If you want script to keep loading no matter what, you may want to experiment with resolving promises when onerror is called.
注意:对于拒绝承诺,您可以尝试使用scriptElement。不过,在loadScript()函数中,我遇到了一些奇怪的行为。如果您希望脚本无论如何都保持加载,那么您可能希望在调用onerror时尝试解析承诺。