2017-07-13 17 views
2

この質問は、角度バージョンthis questionです。この試みは、次の問題が付属していますコンポーネントを別の親コンポーネントに角で移動する

class NewParentComponent { 

    constructor(elRef: ElementRef) { 
    elRef.nativeElement.appendChild(myMovableElement); 
    // where the reference to myMovableElement may come from a service. 
    } 
} 

  1. 我々は角度で直接DOMを操作することになっていません

    次のスニペットは、私の最初の試みをまとめました。何らかの形でRendererでコンポーネントを実現できますか? - @ ThinkingMediaの答えでは、Renderer2を使用してください。

  2. 子コンポーネントを移動した後に元の親コンポーネントが破棄された場合、子コンポーネントに対してngOnDestroyメソッドが呼び出されます。

this Plunkerを参照してください。このPlunkerはAngular Dynamic Component Loader exampleの上に構築されています。ブラウザのコンソールログを開き、 "destroyed!"広告のバナーが変更されるたびにテキストが記録されます。テキストがドロップボックスにドラッグされました。

+0

コンポーネントやDOMノードを移動する必要がありますか?コンポーネントの場合は、どのように作成しますか? –

+0

親コンポーネントから別の親コンポーネントに子コンポーネント(ノードだけでなく)を移動(ドラッグ/ドロップ)する必要があります。子コンポーネントが移動されると、元の親コンポーネントが破壊され、子コンポーネントの 'ngOnDestroy'メソッドを呼び出さないようにする必要があります。 –

+0

大丈夫ですが、動的に作成して注入しますか?プランカを作成する。レンダラーはコンポーネントを動かすことであなたを助けません –

答えて

4

oldParentViewContainerRef.detach(index); 
newParentViewContainerRef.insert(viewRef); 

indexは、ビュー・コンテナ内の子コンポーネントのビューのインデックスです。

let index = oldParentViewContainerRef.indexOf(viewRef); 

viewRef相当子コンポーネントのビューに:それは、以下を用いて得ることができます。子コンポーネントがComponentFactoryResolverの助けを借りて、プログラムで作成された場合にのみ、私の知る限り、viewRefを手に入れることができます。

let factory = componentFactoryResolver.resolveComponentFactory(MyChildComponentType); 
let componentRef = oldParentViewContainerRef.createComponent(factory); 
let viewRef = componentRef.hostView(); 

あなたが間コンポーネントを移動できるようにしたい場合は、ここでお持ち帰りは、あります異なる親コンポーネントを使用する場合は、静的にHTMLに記述するのではなく、プログラマチックにこれらの可動コンポーネントを作成してください。これにより、ViewContainerRefと一緒にうまく動作する可動コンポーネントのインスタンスがViewRefになります。

例:Plunkerを参照してください。

0

DOMを操作することはお勧めしませんが、必ずしも間違っているとは限りません。たとえば、複雑なUIコンポーネントでは、ほとんどの場合、DOMを直接操作する必要があります(たとえば、ダイアログやドロップダウンの特定の実装)。避けるべきことは、開発者が角度をつけずにDOMを操作し、操作がもはや必要なくなった後にDOMをクリーンアップすることができない、漏れです。

DOM内でコンポーネントを移動するとき、ラッパーの内部でコンポーネントを移動すると最も効果的です。たとえば、モーダルコンポーネントにコンポーネントを含めると、モーダルの親要素はDOM内にあり、コンポーネントが追加されたレベルにネストされ、モーダルの子要素がbodyタグに追加されます。モーダルを閉じる必要がある場合、ダイアログの子要素はラッパーに戻され、コンポーネントはラッパーに戻されます。

2

はい、Renderer2クラスでこれを行うことができます。これは推奨される方法です。このクラスを使用する理由は、アプリケーションをAngular Universalと互換性を保つためです。

AngularはAngularJSのようにDOMツリーに結合されません。 Angularは、コンポーネントとDOM間の結合を処理するオブジェクトをViewRef作成します。これは、ViewRefで使用されるネイティブ要素を、変更留置ツリーまたは注入ツリーを破ることなく移動できることを意味します。

Renderer2クラスはAPIメソッドに制限がありますが、それはあなたが必要とする方法を持っています。

abstract appendChild(parent: any, newChild: any): void; 
abstract insertBefore(parent: any, newChild: any, refChild: any): void; 
abstract removeChild(parent: any, oldChild: any): void; 

コンポーネントとしてウィンドウを持つUIライブラリを作成しました。これらのウィンドウは親ウィンドウパネルにドッキングできます。私が行うことができる唯一の方法は、コンポーネントのDOM要素を移動することでした。

私の懸念は、コンポーネントのライフサイクルです。私の窓が破壊されると、それらの要素は元の場所に戻されます。要素が別の親によってDOMから削除された場合、ngOnDestroyが呼び出されるかどうかはわかりません。ViewContainerRefを使用して達成することができる別の親コンポーネントから子コンポーネントを移動

+0

ありがとう@ThinkingMedia。私は[Renderer documentation](https://angular.io/api/core/Renderer)の廃止予定を見落とし、[Renderer2](https://angular.io/api/core/Renderer2)も見ていませんでした。 )。 UIライブラリとライフサイクルに関するあなたの経験は、実際には私のユースケースのように聞こえます。 Renderer2でコンポーネントを移動しても、ライフサイクルに問題があります。私の状況は以下の通りです。 –

+1

私は2つの親コンポーネント、WindowAとWindowBを持っています。 WindowAは動的に作成され破棄されます。 WindowAが作成される(すなわち開かれる)とき、ユーザは子コンポーネントをWindowBに移動(ドラッグ・アンド・ドロップ)することができる。 WindowAが破棄される(すなわち閉じられる)とき、ngOnDestroyメソッドは依然としてWindowBに移動された子コンポーネントで呼び出される。 –

+0

@samherrmannクール、明確化のおかげで:) – cgTag

関連する問題