简体   繁体   English

加载模板dom时,angular2模板/钩子中的脚本标记

[英]script tag in angular2 template / hook when template dom is loaded

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. 组件选择器/主机嵌入在php回显的普通html流中,用于替换预定义的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. 问题是在正常站点上,使用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. 由于脚本标记在组件模板加载完成之前被回显,因此jquery调用将找不到模板DOM的元素。 Putting the script tag inside my template (at the end) does not work; 将脚本标记放在我的模板中(最后)不起作用; it simply seems to get ignored. 它似乎被忽略了。

<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 (eg through the binding of my component being updated externally) I need to call $(document).foundation() . 此外,该站点使用基础框架,每次向页面添加新元素时(例如,通过外部更新我的组件的绑定),我需要调用$(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. 所以我的问题是,当我不知道我的模板是否已经完成创建时,如何在我的模板DOM上调用jquery。 The onload handler doesn't work either when defined in my component template. 在我的组件模板中定义时,onload处理程序不起作用。

I have read about AfterViewInit, but I'm kind of overwhelmed with it. 我读过有关AfterViewInit的内容,但我对此感到不知所措。 Could someone please push me in the right direction? 有人可以请我朝正确的方向努力吗?

How can I find out when the template of my component has been fully inserted into the "main" DOM? 如何找出组件模板何时完全插入“主”DOM?

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://stackoverflow.com/a/9413803/217408 另请参见https://stackoverflow.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 template / hook中的脚本标记

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或更高版本 ,该解决方案将起作用,它具有对async / await的本机支持并转换为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.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")
}

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. 注意:对于promise promise,你可以尝试在loadScript()函数中使用scriptElement.onerror = reject ,但是,在这种情况下我遇到了一些古怪的行为。 If you want script to keep loading no matter what, you may want to experiment with resolving promises when onerror is called. 如果您希望脚本无论如何都要继续加载,那么您可能希望在调用onerror时尝试解析promise。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM