Angular 2 Как заставить Angular обнаруживать изменения, сделанные вне Angular?

Я пытаюсь создать простой пример проекта для проверки механизма обнаружения угловых изменений: я создаю чистый объект 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;

Я пытаюсь сделать следующее: когда я вызываю функцию Tryout.printme() обычно с помощью onclick (полностью вне угла), я хочу, чтобы angular обнаружил изменение и обновил экран.

Мне это удалось: когда я вызываю Tryout.printme() из компонента (функция changeme() вызывает Tryout.printme()), Angular обнаруживает изменения и обновляет пользовательский интерфейс, что нормально. Кроме того, когда я изменяю внешний вид angular и вызываю consoleLogMe() из Angular, он записывает измененный текст и обновляет пользовательский интерфейс.

Я думаю, мне нужно выполнить Tryout.changeme() в той же зоне, в которой каким-то образом работает Angular. Есть идеи? У меня есть большой проект, который выполняется в чистом javascript/jquery, и теперь мне нужно медленно переписывать шаблоны руля в компоненты angular 2, не касаясь модели (пока). Для этого мне нужно заставить модель работать в той же зоне, что и угловая.

Если бы я хотел сделать что-то подобное в Angular 1, я бы просто использовал $scope.$ Apply, чтобы это работало.

Вот рисунок из примера:

1 ответ

Решение

Вы можете сделать это, экспортировав NgZone внутри вашего углового приложения. Обычно вы должны делать все внутри Angular, но если вы действительно хотите выполнить свою логику из Angular, вам нужно получить правильное zone, как вы сказали.

Этот трюк злоупотребляет инъекцией зависимостей Angular и перехватывает внедренные zone на window объект, как показывает этот вопрос. Объявление зависимости от 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
  }
}

После угловой загрузки вы должны иметь zoneImpl глобальная переменная. Вы можете использовать run способ выкинуть Angular.

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

Живая демоверсия.

Другие вопросы по тегам