2016-11-03 13 views
4

私は角度2.0.1を使用しています。@ContentChildの角2参照動的インスタンス

私は<ng-content>経由で他のコンポーネントを取り込むことができるコンポーネントを持っています - これは素晴らしい作品です。

私が問題になったのは、注入されたコンポーネントを参照したいときです。私は<ng-content>だけ今まで私が言うことができる一つの構成要素になることを知っていた場合

:(私はなるだろう唯一の仮定は任意の注入されたコンポーネントは、特定のインターフェイスを実装していることである) @ContentChild(MyComponent) dynamicTarget: IMyComponent;それは任意の構成要素とすることが可能性があるため、それがトリッキーになります。

また、<ng-content #dynamicTarget'>を試した後、@ContentChild('dynamicTarget') dynamicTarget: IMyComponent;と言っていますが、これは未定義です。

誰かが私がそれに関数を呼び出そうとすることができるように、このことがコンポーネントのインスタンスであることをAngular 2に伝える方法を知っていますか?

ユースケースをさらに明確にするために、コンテンツとして任意のコンポーネントを取り込むことができる複数ステップのウィザードがあり、そのコンテンツに対してvalidate関数を呼び出す必要があります(ここでも、 )

+1

"問題を解決する最善の方法は、もはやそれを持っていないことを確認することです"。 手順がコンポーネントとして定義されている場合、transclusion(NgContent)を使用する代わりにウィザードで手動で作成し、構成として渡すことができます。例えば、このPlunker(http://plnkr.co/edit/6I5e53fOzu9ywS3FzHlc)をチェックしてください。 –

+0

@ S.Klechkovski私の非常に最初のプロトタイプは実際にはconfigの一部として実際に配列の配列を使用していました。代わりに 'ng-content 'を使うことができるのであれば、私はもっと興味があると思います。 (もしあなたのウィザードをHTMLとconfigオブジェクトの両方で構築する以外の理由がない場合)。私はそれがconfigオブジェクトに戻る可能性がないと思います。 – Johannes

答えて

3

1つのアプローチは、任意の動的コンポーネントに同じものを与えることができます。 私は#thoseThingsを与えました。 (これは@Missingmanualとほぼ同じだと思います)

PLUNKER(マッチはコンソールを参照してください。)

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div [style.border]="'4px solid red'"> 
    I'm (g)Root. 

    <child-cmp> 
     <another-cmp #thoseThings></another-cmp> 
    </child-cmp> 
    </div> 
    `, 
}) 
export class App { 
} 


@Component({ 
    selector: 'child-cmp', 
    template: ` 
    <div [style.border]="'4px solid black'"> 
     I'm Child. 
     <ng-content></ng-content> 
    </div> 
    `, 
}) 
export class ChildCmp { 
    @ContentChildren('thoseThings') thoseThings; 

    ngAfterContentInit() { 
    console.log(this.thoseThings); 

    this.validateAll(); 

    if(this.thoseThings){ 
    this.thoseThings.changes.subscribe(() => { 
     console.log('new', this.thoseThings); 
    }) 
    } 
    } 

    validateAll() { 
    this.thoseThings.forEach((dynCmp: any) => { 
     if(dynCmp.validate) 
     dynCmp.validate(); // if your component has a validate function it will be called 
    }); 
    } 
} 


@Component({ 
    selector: 'another-cmp', 
    template: ` 
    <div [style.border]="'4px solid green'"> 
     I'm a Stranger, catch me if you can. 
    </div> 
    `, 
}) 
export class AnOtherCmp { 
} 
+0

これは実際には本当に涼しいです、私はそれのように外側にIDを投げることを考えていませんでした(私は、ngコンテンツ自体は、動作しませんでした)。これは実装者がそこにIDを投げる必要があるという意味では理想よりも若干少なくなりますが、これはページ上の複数のコンポーネントを許可してより読みやすくなるため、設定手法よりも優れています。これまではこれが最善の選択肢です。 Ankitありがとうございました。 – Johannes

+1

私は自分のコードでこれを実装することができましたが、実際にはこの結果が本当に好きなので、これを受け入れて賞金を授与します。 Ankitにもう一度感謝します。 – Johannes

+0

私は本当にうれしく思っています。寛大な感謝、ありがとう;) –

1
で動作させることができなかったことにより、クエリ3210
@NgModule({ 
    imports: [ BrowserModule ], 
    declarations: [ App, Parent, Transcluded1, Transcluded2 ], 
    providers: [ 
    {provide: TranscludedBase, useExisting: Transcluded1, multi:true} 
    {provide: TranscludedBase, useExisting: Transcluded2, multi:true} 
    ], 
    bootstrap: [ App ] 
}) 

Plunker example

  • あなたは、ウィザードの手順の代わりに、タブが動的コンポーネントの作成Angular 2 dynamic tabs with user-click chosen componentsを使用することができます。

  • もう一つの方法は、にあるそれらを投影することに加えて、入力に明示的要素を渡す:

Plunker example

+0

[Issue#8580](https://github.com/angular/angular/issues/8580)は非常によく似ているようです(おそらくサポートされています)。唯一の違いは、動的コンポーネントとハードコードされたコンポーネントを使用していることです。私は先にAngularの問題を提出して、これについてより良い洞察を得ることにしました。 – Johannes

+0

さらに、2番目の例の妥協案が好きですが、コンポーネントの配列が必要ですが、基本的にはすべてを2回定義することで保守が難しくなりますが、例と代替ソリューションを理解できます。 – Johannes

+0

これは単なる回避策であることに同意します –

-1

を、あなたのすべてを知っている場合コンポーネントはvalidateを持ち、同じインタフェースを実装します。 IValidate、その後、あなたはそれが要求されたインタフェースに適合するよう

@ContentChild('IValidate') dynamicTarget: IValidate; 
// ... 
this.dynamicTarget.validate(); 

角度は限り正確なクラスを気にしませんと言うことができます。

+1

これがうまくいくとすれば良いでしょう。しかし、インターフェイスと抽象クラスの両方で、私はこのテクニックでは成功しませんでした。あなたがこれを働かせることができるなら(plunkrで)、私はそれを最良の答えとして受け入れてくれることを嬉しく思います。 – Johannes