2017-01-05 8 views
1

デコレータTopicClassを作成して、装飾されたコンポーネントにプロパティと関数を追加したいとします。この関数は、注入されたサービスにアクセスする必要があります。 どうすればいいですか?ここで依存関係注入サービスにアクセスする角2のクラス・デコレータ

に失敗した試みたものです:


@Component({ 
    selector: 'home', 
    styleUrls: ['./home.component.css'], 
    templateUrl: './home.component.html' 
}) 
@TopicClass('home') 
export class HomeComponent { 
    constructor(private topicService: TopicService) { } 
} 

は私が挿入された機能ngAfterViewInitを通じて注入サービスにアクセスすることはできません。


export function TopicClass(title: string) { 
    return function (target: Function) { 
    const original = target; 

    function construct(constructor, args) { 
     const c: any = function() { 
     return constructor.apply(this, args); 
     } 
     c.prototype = constructor.prototype; 

     const newInstance = new c(); 
     newInstance['topic'] = new Topic(title, ''); 

     newInstance['ngAfterViewInit'] =() => { 
     newInstance['topicService'].setTopic(newInstance['topic']); 
     } 
     return newInstance; 
    } 

    const ctor: any = (...args) => { 
     console.log("Service: " + original.prototype.topicService); 
     return construct(original, args); 
    }; 

    ctor.prototype = original.prototype; 
    return ctor; 
    } 
} 

問題はnewInstance['topicService']は未定義です。

私はテストのための単純な角度のプロジェクト設定している

:私も意図したとおりに動作し、簡単な活字体のプログラムに問題を再現してみました https://github.com/ptea/angular-class-decorator-test

https://github.com/ptea/angular-class-decorator-test/blob/master/src/app/services/topic.service.ts

を:


newInstance['printStreet'] =() => { 
    console.log(`printFirstnameStreet: ${newInstance['firstname']}, ${newInstance['street']}`); 
} 

https://github.com/ptea/angular-class-decorator-test/blob/master/dashboard.ts

任意ideこの問題の解決策として?

答えて

1

TopicServiceが定義されていない理由は、コンポーネントに注入されたことがないためです。現在のデコレータでは、引数のないコンストラクタとしてHomeComponentのコンストラクタを再定義しています。これは、AngularのDIを乱しているため、コンポーネントがインスタンス化されたときにTopicServiceが注入されません。

あなたが望む目的を達成するには、HomeComponentのコンストラクタを変更せず、その代わりにngOnInitメソッドをタップします。 ngOnInitメソッドは、コンポーネントのライフサイクルごとに1回呼び出され、固定数のパラメータ0(別の関数内で簡単に折り返すことができるため)が理想的です。類似している場合は、ngAfterViewInit関数を使用して、必要に応じてサービスを使用することができます。一緒に働くすべての

export function TopicClass(title: string) { 
    return function (target: Function) { 

    let targetNgOnInit = target.prototype.ngOnInit; 
    target.prototype.ngOnInit = function(){ 
     this.topic = new Topic(title, 'subTitle'); 

     if(targetNgOnInit){ 
     targetNgOnInit.apply(target); 
     } 
    } 

    let targetNgAfterViewInit = target.prototype.ngAfterViewInit;   
    target.prototype.ngAfterViewInit = function(){ 
     this.topicService.setTopic(this.topic); 

     if(targetNgAfterViewInit){ 
     targetNgAfterViewInit.apply(target); 
     } 
    } 

    return target; 
    } 
} 

Demo Plunkr:ここ

はあなたの望ましい結果をacheiveするTopicClassDecoratorを修正することができる方法です。

+0

。あなたのコードは、 'return target'が削除されたときに機能します。 –

+0

これは天才です! – Slick86

0

私は最終的にngOnInit機能を上書きせずに、次の解決策と一緒に行きました:私は、ターゲットのコンストラクタの代わりに、空からの引数を期待していた


export function TopicClass(title: string) { 
    return function (target: Function) { 
    target.prototype.topic = new Topic(title); 

    let targetNgAfterViewInit = target.prototype.ngAfterViewInit;   
    target.prototype.ngAfterViewInit = function() { 
     this.topicService.setTopic(this.topic); 

     if(targetNgAfterViewInit){ 
     targetNgAfterViewInit.apply(target); 
     } 
    } 
    } 
} 
関連する問題