2015-12-07 3 views
9

にロードされたときに、私はかなりこだわっていると私の問題を解決する方法がわからない...スクリプトタグテンプレートDOMは

簡体:私はに基づいて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 
    }  
} 

成分セレクタ/ホストは、PHPによってエコー通常のHTMLフローに埋め込まれ、事前に定義されたULISTを置き換えるために使用されます。問題は、通常のサイトでは、ulistの後のscriptタグを使ってjqueryの魔法をリストに適用したことです。

コンポーネントのテンプレートのロードが完了する前にスクリプトタグがエコーアウトされるため、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> 

また、サイトには、Foundationフレームワークを使用し、それぞれの時間は、新たな要素が(外部から更新されて、私のコンポーネントの結合を介して例えば)ページに追加された私は$(document).foundation()を呼び出す必要があります。

私の質問は、テンプレートが作成されたかどうかわからないとき、テンプレートDOMでjqueryを呼び出すためにどのように達成できますか。 onloadハンドラは、コンポーネントテンプレートで定義されている場合でも動作しません。

私はAfterViewInitについて読んだことがありますが、私はそれに圧倒されています。 誰かが私を正しい方向に押し込んでくれますか?

コンポーネントのテンプレートが「メイン」DOMに完全に挿入されたことを確認するにはどうすればよいですか?

+2

[APIドキュメント](https:// angular。io/docs/ts/latest/api/core/AfterViewInit-interface.html)を使用して、コンポーネントにngAfterViewInit()メソッドを追加し、そこでjQueryコードを呼び出してみることができます。 –

+0

@ MarkRajcok +1。 OPは、AfterViewInitを実装する必要があることに注意してください。また、ang2で絶対に必要な場合を除いて、jQuery(テンプレートとデータバインディングのソリューションを使用することを推奨)を使用したくないことに注意してください。 – drewmoore

+0

テンプレートが完全にロードされたときに 'AfterViewInit'と' AfterContentInit'のどちらも起動しませんテンプレートは非同期に配信されるソースにバインドされています)。バインディングが変更されたときに、 '#a(click)=" addHandler(a) "'でテンプレート自体にハンドラを作成し、 'AfterViewChecked'を使って' jQuery(document).foundation() 'を適用することで解決しました。ありがとう! – ch40s

答えて

20

コンポーネントテンプレート内のスクリプトタグは削除されます。この問題を回避するには、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); 
} 

だけのスクリプトをロードするためにrequire()を使用するより良い方法があるかもしれないもhttps://stackoverflow.com/a/9413803/217408

を参照してください。また、ngAfterViewInit()

を参照して、動的にスクリプトタグを作成することです。

は、私は同じ問題に遭遇したが、さらに私は、並列にロードされた可能性があり、そのいくつかのスクリプトの数と、シリーズの他にロードしなければならなかったもscript tag in angular2 template/hook when template dom is loaded

+0

ありがとう。私が投稿したとき、私はちょうど角度で始めました、そして私は完全に間違ったアプローチを使用しました。クリックハンドラをテンプレート要素に追加するだけでしたが、この場合は、 'のように、angle2のテンプレート構文を使用するほうが快適です。 – ch40s

+0

確かに、外部スクリプトを使わないのが一番です:) –

5

を参照してください。並行してロードすることができます任意のスクリプトの場合

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

、あなたがPromise.allを活用することができます:このソリューションでは、ES3/ES5にasync/awaitとtranspilesをネイティブでサポートしていTypeScript 2.1 or greaterを、使用している場合に動作します

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

注:約束除去のために、あなたはしかし、私はこのような状況では、いくつかの風変わりな行動が発生し、loadScript()機能にscriptElement.onerror = rejectで作業をしてみてください。スクリプトが何をしてもロードし続けるようにするには、onerrorが呼び出されたときに約束を解決することを試してみてください。