2017-08-19 10 views
2

コンテキストで構造ディレクティブを作成しました。構造ディレクティブのコンテキストが更新されていません

@Directive({selector: '[myDir]'}) 
export class MyDir implements OnInit { 
    constructor(private templateRef: TemplateRef<any>, 
       private viewContainerRef: ViewContainerRef, 
) { } 

    public context = {$implicit: false} 

    ngOnInit() { 
    this.viewContainerRef.createEmbeddedView(this.templateRef, this.context) 
    } 
} 

これは私の使い方です。

<pre *myDir="let context">Context: {{ context | json}}</pre> 

テンプレートがビューに正しくインストールされており、Context: falseが期待どおりに存在しています。

ただし、コンテキストを変更しようとすると、はビューに反映されません。 ngTemplateOutlet spec from the Angular repoで判断すると、コンテキストが変更されたときに更新する必要があります。 私のコードに間違いがありますか、または仕様を誤解していますか?

また、私はCRを注入して手動で変更検出をトリガーしようとしましたが、動作しませんでした。私の実際のケースでは、変化はマウスのイベントを聞く観察可能なサブスクリプションでトリガされるはずでしたが、ここでは簡単な間隔のデモがあります。

Observable 
    .interval(500) 
    .map((_, i) => i % 2 == 0) 
    .takeUntil(this.destroy$) 
    .subscribe(context => { 
    this.context = {$implicit: context} 
    console.log('Context is now', this.context.$implicit) 
    }) 

context$もののは変化、およびコンソールに示すある変更を行い、ビューが更新されません。 Here's a demo on StackBlitz


いくつかの再読み込みの後で、Blitzが怒ってしまったため、私はdestroyに登録解除を追加しました。また、AppComponentに対する0.5秒間隔の単なるカウンタであるテスト観測可能性が追加されました。これは、ディレクティブとは無関係です。これは、アプリケーションが正常に機能していることを確認するだけであり、CDサイクルは通常、アプリ全体で適切に実行されています。私はどこでもOnPushを使用しません。

答えて

3

Javascriptは非常にintreresting言語です。我々はcontextを作成し、createEmbeddedView関数に渡されたとき

let view: any = {}; 
function detectChanges() { 
    console.log(view.context); 
} 

function createEmbeddedView(context) { 
    view.context = context; 
} 

let context = { x: false }; 
createEmbeddedView(context); 

detectChanges(); // prints { x: false } 

は、以下のコードを考えてみましょう。

contextを変更しましょう。我々はそれがで動作しながら、私たちの出力は、最初の場合には変更されません見ることができるように)変更は

context.x = true; 

detectChanges(); // prints { x: true} Hooray!!! 

を内部)

context = { x: true }; 

detectChanges(); // prints { x: false } 

2自体を変更します。我々はそれを2つのオプションが行います2番目のケース。これは、javascriptでオブジェクトby sharingを渡すためです。

これは、特定の種類の値渡しです。パラメータそのものを変更すると、関数内で与えられた項目には何の影響も与えません。しかし、いくつかのプロパティを変更すると、アイテムが変更されます。

this.context.$implicit = context; 

https://stackblitz.com/edit/so-context-question-a4n5yx?file=app%2Fapp.component.ts

+0

時々私は角度とRxJSに巻き込まああ、そんなに私にはJavaScriptの基本を忘れて:

は、だからあなたの場合のために、あなたは次のように自分のコンテキストを変更することができます。 これはテストでなぜ動作するのかについても説明しています。これは、_template_バージョンの 'ngTemplateOutlet'をテストしています。つまり、すべてのCDサイクルで同じ参照が渡されます。私の場合、CDはその2つのオブジェクトが同期していなければならないことを単に知る方法がないので、それを実行できません。 –

関連する問題