web-dev-qa-db-ja.com

Angular 2 Angularの外部で行われた変更を検出するためにAngularを取得する方法は?

angular 2変更検出メカニズムをテストする簡単なサンプルプロジェクトを作成しようとしています:メインインデックスページのスクリプトタグに純粋なjavascriptオブジェクトを作成します。これには次のものが含まれています。

        var Tryout = {};
        Tryout.text = "Original text here";
        Tryout.printme = function(){
            console.log(Tryout.text);
        }
        Tryout.changeme = function(){
            Tryout.text = "Change was made";
        }

コンソールログに記録する関数と、テキストプロパティを変更する関数があります。

Angular 2)では、コードは次のようになります。

import {Component} from "angular2/core"

@Component({
    selector: 'my-app',
    template: `
        <h1>{{TryoutRef.text}}</h1>
        <input type="text" [(ngModel)]="TryoutRef.text">
        <button (click)="consoleLogMe()">Console Log</button>
        <button (click)="changeMe()">Change me inside</button>
    `
})

export class MyApp{

    TryoutRef:any = Tryout;
    constructor(){
    }
    changeMe(){
        this.TryoutRef.changeme();
    }
    consoleLogMe(){
        console.log(this.TryoutRef.text);
    }

}
declare var Tryout:string;

私がやろうとしていることはこれです:通常onclick(完全にangularの外側)で関数Tryout.printme()を呼び出すとき、angularで変更を検出し、画面を更新します。

私はこの点に成功しました:コンポーネントからTryout.printme()を呼び出すと(changeme()関数はTryout.printme()を呼び出します)、Angularは変更を検出し、UIを更新します。また、外部から変更するとangularそしてAngular)からconsoleLogMe()を呼び出すと、変更されたテキストがログに記録され、UIが更新されます。

Angularが何らかの形で実行されているのと同じゾーンでTryout.changeme()を実行する必要があると思います。何かアイデアはありますか?純粋なjavascript/jqueryで実行される大きなプロジェクトがあります。モデルに触れずに、ハンドルバーテンプレートをangular2コンポーネントにゆっくりと書き直す必要があります。そのためには、angularと同じゾーンでモデルを強制的に実行する必要があります。

Angular 1でこのようなことをしたい場合は、$ scope。$ applyで動作します。

ここに例からのgifがあります:

enter image description here

17
Denko Mancheski

これを行うには、Angularアプリ内でNgZoneをエクスポートします。通常、Angular内ですべてのことを行う必要がありますが、本当にAngularからロジックを実行したい場合は、あなたが言ったように、正しいzoneを取得する必要があります。

このトリックは、 この問題 が示すように、Angularの依存性注入を悪用し、注入されたzonewindowオブジェクトにフックします。 NgZoneへの依存関係を宣言し、エクスポートのために_window.zoneImpl_に割り当てます。

_//our root app component
import {Component, NgZone} from 'angular2/core'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>

    </div>
  `,
})
export class App {
  constructor(zone: NgZone) {
    this.name = 'Angular2'
    window.app = this
    window.zoneImpl = zone
  }
}
_

Angularブートストラップ後、zoneImplグローバル変数が必要です。runメソッドを使用してAngular off 。

zoneImpl.run(() => window.app.name = "new name!")

ライブデモ

11