2016-03-17 25 views
33

私はTypescriptでAngular2アプリケーションを構築しており、Typescriptが提供するクラスシステムの機能(クラス継承を読んでください)を使用したいと考えています。しかし、Angular2は派生クラスではうまくいきません。私は私のアプリケーションを動作させるためにいくつかの助けを求めています。Angular2とクラス継承のサポート

私が直面している問題は、基本クラスがあり、そこからいくつかの子クラスを派生させることです。コンポーネントツリーを構築しているときに、コンポーネントの親子にアクセスできるようにしたいと考えています(どちらの方法でも問題ありません)。コンポーネントの子にアクセスするには、子コンポーネント

  • 使用ContentChildren(またはViewChildren)に親を注入

    1. :私が理解から、Angular2はそれを達成するための2つのオプションを提供しています。

    (ChildComponent)で作業しているクラスの型を知っていればどちらも問題なく動作しますが、これらのコンポーネント(BaseComponent)の基本クラスをセレクタとして使用しようとすると失敗するようです。

    @Component({ 
        selector: 'my-app', 
        template: `<parent-comp> 
         <child-comp1></child-comp1> 
         <child-comp1></child-comp1> 
         <child-comp2></child-comp2> 
        </parent-comp>`, 
        directives: [ParentComponent, ChildComponent1, ChildComponent2] 
    }) 
    export class MyApplication { 
    } 
    

    基本クラスと子クラスは次のように定義されています

    いくつかのコードでそれを可視化するために、次のように私は、アプリケーションコンポーネント/クラスを持っている、(ライブデモのために、このPlunkerを参照してください)

    export class BaseComponent { 
        // Interesting stuff here 
    } 
    
    @Component({ 
        selector: 'child-comp2', 
        template: '<div>child component #2</div>' 
    }) 
    export class ChildComponent2 extends BaseComponent { 
    } 
    
    @Component({ 
        selector: 'child-comp1', 
        template: '<div>child component #1</div>' 
    }) 
    export class ChildComponent1 extends BaseComponent { 
    } 
    

    そして、Parentクラスは、その子を数えるロジックを持っています。

    @Component({ 
        selector: 'parent-comp', 
        template: `<div>Hello World</div> 
        <p>Number of Child Component 1 items: {{numComp1}} 
        <p>Number of Child Component 2 items: {{numComp2}} 
        <p>Number of Base Component items: {{numBase}} 
        <p><ng-content></ng-content> 
        ` 
    }) 
    export class ParentComponent implements AfterContentChecked { 
    
        @ContentChildren(ChildComponent1) contentChild1: QueryList<ChildComponent1> 
        @ContentChildren(ChildComponent2) contentChild2: QueryList<ChildComponent2> 
        @ContentChildren(BaseComponent) contentBase: QueryList<BaseComponent> 
        public numComp1:number 
        public numComp2:number 
        public numBase:number 
    
        ngAfterContentChecked() { 
        this.numComp1 = this.contentChild1.length 
        this.numComp2 = this.contentChild2.length 
        this.numBase = this.contentBase.length 
        } 
    

    (繰り返しますが、あなたはライブデモhereを見ることができます)

    予想通り最初の二つのカウンタの出力があります。 2つのChildComponent1と1つのChildComponent2の子があります。残念ながら、BaseComponentカウンタはこれらのカウンタの合計を表示せず、0を表示します。子でBaseComponent型のクラスは見つかりません。

    ParentComponentもBaseComponentから継承し、ChildComponentに注入したい場合も同じことが起こります。インジェクタはParentComponentの特定の型を必要とし、基本クラスでは動作できません。

    Angular2で派生クラスを操作する方法の手掛かりはありますか?私は何かを逃したり、何かを不可能にしようとしています

  • +0

    私はこれを考えます子どものメタデータだけを使用して比較を行うので、BaseComponentが含まれていないので、Angularの問題です。具体的には、ContentChildrenとViewChildrenの実装ですQueryListに追加されました。ただし、プロバイダに[BaseComponent]を追加すると、コンポーネントのメタデータにBaseComponentインスタンスが存在し、継承が使用されていない場合は現在の子がQueryList EVENに追加され、BaseComponentの別のインスタンスも作成されます子供。 –

    +0

    [Plunker link](http://plnkr.co/edit/dpdJvK06OY3o44pWiAMG?p=preview)。 –

    +0

    @NikolaNikolov:私はBaseComponentをプロバイダとして持つことであなたの提案を試しました。これは実際にBaseComponentを親のContentChildrenのリストに追加します。ただし、これらのインスタンスは、前述のとおり、派生クラスのインスタンス自体とは異なります。それはあまりにも悪いです。 – Sjoerd

    答えて

    32

    由来成分をベース成分をエイリアシング、各由来成分にプロバイダを追加します。

    @Component({ 
        selector: 'child-comp2', 
        template: '<div>child component #2</div>', 
        providers: [{provide: BaseComponent, useExisting: forwardRef(() => ChildComponent2) }] 
    }) 
    export class ChildComponent2 extends BaseComponent { 
    } 
    
    @Component({ 
        selector: 'child-comp1', 
        template: '<div>child component #1</div>', 
        providers: [{provide: BaseComponent, useExisting: forwardRef(() => ChildComponent1) }] 
    }) 
    export class ChildComponent1 extends BaseComponent { 
    } 
    

    Plunker:http://plnkr.co/edit/5gb5E4curAE2EfH2lNZQ?p=preview

    +0

    ありがとう、それは動作するようです!また、別のコンポーネントインスタンスではなく、派生したインスタンスを実際に取得したかどうかを確認したところ、正しく動作するようにも見えました。http://plnkr.co/edit/KSchL5dOCebxEQU692u9?p=preview – Sjoerd

    +0

    どのようにBaseClassの依存関係を処理しますかコンストラクタで? –

    +0

    @TobiasGassmann:新しい質問を特定の例で投稿する必要があります。 –

    0

    あなたがリストを作成しContentChildrenクエリでのローカルテンプレート変数を使用することができます共有ベースクラスを持つすべてのコンポーネントの以下のコードはplunkです。このアプローチは、Kara Ericksonのブログ記事のRookie mistakesでの示唆に基づいています。

    <app-container> 
        <app-child1 #child></app-child1> 
        <app-child1 #child></app-child1> 
        <app-child1 #child></app-child1> 
        <app-child1 #child></app-child1> 
        <app-child2 #child></app-child2> 
        </app-container> 
    

    これは、共有ベースコンポーネントを持つすべてのコンポーネントを選択するために使用することができます:それぞれの子コンポーネントが#childでマークされたテンプレートで

    import { Component, QueryList, ContentChildren, ViewChildren, AfterViewInit, AfterContentInit } from '@angular/core'; 
        import { BaseComponent } from '../base/base.component'; 
        import { Child1Component } from '../child1/child1.component'; 
        import { Child2Component } from '../child2/child2.component'; 
    
        @Component({ 
        selector: 'app-container', 
        templateUrl: './src/container/container.component.html' 
        }) 
        export class ContainerComponent implements AfterContentInit { 
        @ContentChildren('child') allChildren: QueryList<BaseComponent>; 
        @ContentChildren(Child1Component) child1Chdilren: QueryList<Child1Component>; 
        @ContentChildren(Child2Component) child2Chdilren: QueryList<Child2Component>; 
    
        constructor() { } 
    
        ngOnInit() { 
        } 
    
        ngAfterContentInit() { 
        } 
    
        }