2016-05-27 3 views
2

Angular2 RC1 Webアプリケーション内で外部から変更されたDOMに関する助けが必要です。シナリオは単純です:私はこのAngular2、ZoneJS、外部で変更されたDOM

<div id="my-svg-canvas"></div> 

typescriptedコンポーネントのようなIDと空のdivが含ま応じたテンプレートを持つコンポーネントを持っている含まれているプレーンなJSファイルから関数をトリガーngOnInitメソッドを持っていますindex.htmlのscript-tagを介してこの関数はSVGを上記の "div"タグに表示します。 SVGには、コンポーネント内のいくつかのメソッドを参照するオン・クリック・ディレクティブを含むいくつかのa要素が含まれています。

これは、SVGが完全に書かれた後、$ scope。$ apply()を呼び出した後、Angular1でうまくいきました。今、Angular2では、私のコンポーネント内のそれぞれのメソッドがトリガされません。

私は知っている、ZoneJSは今DOMの変更を検出する責任があります。私はこれがAngular-managedコンポーネントの内部でレンダリングされたDOM全体に対して自動的に行われることを期待していました。次の試みは、このように、私のコンポーネントでNgZoneを注入し、明示的にその中のレンダリング機能を実行することでした:

ngOnInit() { 
    this.ngZone.run(() => {renderSVG(this.myData, "my-svg-canvas");}) 
} 

ません成功のいずれか: - :問題以来、/また、私はMutationObserver(Angular2 Directive: How to detect DOM changesこのスレッドを参照してください)に登録私と少し似ていました。しかし、どちらも解雇されていません。

私はどこを探すべきかわかりません。

注:SVGレンダリングフレームワークが無効な属性の設定を拒否したため、「(クリック)」ではなく「オンクリック」を使用する必要がありました。明らかに、括弧で始まる属性はHTMLでは問題ありませんが、XMLでは正しくありません。しかし、両方の指令が完全に交換可能であるため、これは問題ではありません。

PS:

と呼ばれるレンダリング方法がSVG.jsフレームワークを利用し、次のようになります。

function renderSVG(dataParam, elementIdParam) { 
    draw = SVG(elementIdParam).spof(); 
    initAndPaint(draw, dataParam); 
    return draw; 
} 

そして

<a id="SvgjsA1033" on-click="showVal('W1')" class="union"> 
libにSVG.jsによって生成されたタグ

生成されたSVGコードをテンプレートに貼り付けると、すべて正常に動作します。

答えて

2

私はAngularが動的に追加されたHTMLを解析すると考えています(Angular2 - catch/subscribe to (click) event in dynamically added HTML参照)。

renderSVG()を呼び出した後は、DOMをトラバースして新しく追加されたa要素を見つけて、手動で追加して後で削除する必要があります。

Dynamically add event listener in Angular 2を参照してください。

さらに複雑なアプローチについては、Equivalent of $compile in Angular 2を参照してください。

+0

最初のリンクで提供されている解決策は、本当に私にうんざりを与えています:-) 私はDynamicLoaderComponentにチャンスを与えてくれました。実際には動作しますが、Angular1の1ライナーと比較して中世のタイムワープバック。十分に公正で、我々はRCを扱っているが、より良い解決策が提示されるべきである。 – Matt

+0

ありがとうございました!実装にあなたの投稿を追加し、それを "受け入れられました"と – Matt

+0

@ user3802631というフラグを付けました。私は完全に同意します。 DynamicLoaderComponentよりも単純なものが必要です。あなたの編集が拒否されたようです。私は別の答えとしてそれを追加することをお勧めします。 –

1

私はあなたのコンポーネントのngAfterViewInitフックメソッドにコードを移動します:

<div #mySvgCanvas"></div> 

@ViewChild('mySvgCanvas') 
mySvgCanvasElt: ElementRef; 

ngAfterViewInit() { 
    var elt = this.mySvgCanvasElt.nativeElement; 
:またあなたが ViewChildデコレータを使用してDOM要素を参照する必要があります

ngAfterViewInit() { 
    this.ngZone.run(() => {renderSVG(this.myData, "my-svg-canvas");}) 
} 

ゾーンを明示的に使用するとは思わないここに必要です...

+0

ありがとうございました。私はあなたが言ったように、まだ働いていませんでした。私は、レンダリングが起こった後、SVG全体がそこにあると、viewchildプロパティをチェックしました。これは良いことです。さらに、私はキャンバスの隣にもう1つのビューチャイルドを追加しました:タグで、SVGと同じようにオンクリック・ディレクティブがあり、ElementRef.nativeElemtensの違いやその違いを確認できます。単一の -nativeelementには__zone_symbol__eventtasks配列が添付されていますが、SVG内のすべてのタグには含まれていません。 私はngZone内でSVGレンダリングを実行しました。違いはありません: -/ – Matt

+0

あなたは 'renderSvg'メソッドの抽出をいくつか提供できますか?ちょうどそれがどのように見えるかを見る... –

+1

もちろん。私が質問の最後に追加したPSセクションを参照してください。 – Matt

1

受理された回答の中でDynamicLoaderComponentを使用して解決策にマークするRajcokのリンク(「もっと複雑なアプローチ」を参照)。このスレッドのクローズとして、これは私の実装です:

constructor(private loader: DynamicComponentLoader, private injector:Injector) {} 

ngAfterViewInit() { 
    let tournamentCanvas = document.createElement("canvas"); 
    renderKOTournamentSVG(this.tournament, tournamentCanvas); 

    @Component({ 
    selector: 'canvas-component', 
    template: tournamentCanvas.outerHTML)} 
    class CanvasComponent {} 

    this.loader.loadAsRoot(CanvasComponent, "canvas-component", this.injector); 
} 
関連する問題