I am trying to create a simple example project to test the angular 2 change detection mechanism: I create a pure javascript object in script tags on the main index page. it contains the following:
var Tryout = {};
Tryout.text = "Original text here";
Tryout.printme = function(){
console.log(Tryout.text);
}
Tryout.changeme = function(){
Tryout.text = "Change was made";
}
One function to console log it, and one to change the text property.
Now in Angular 2 the code looks like this:
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;
What I am trying to do is this: When I call the function Tryout.printme() normally with onclick (Completely outside of angular) I want angular to detect the change and update the screen.
I succeeded to this point: When I call Tryout.printme() from the component (the changeme() function is calling Tryout.printme()), Angular detects the change and updates the UI which is fine. Also, when I change from outside angular and I call consoleLogMe() from Angular it is logging the changed text and updates the UI.
I guess I need to execute Tryout.changeme() in the same Zone that Angular is running in somehow. Any ideas? I have a big project which is done in pure javascript/jquery, and now I slowly need to rewrite the handlebar templates to angular2 components without touching the model (yet). For that I need to force the model to execute in the same zone as angular.
If I wanted to do something like this in Angular 1 I would just $scope.$apply it would work.
Here is a gif from the example:
You can do this by exporting
NgZone
inside your Angular app. Usually, you should do all things inside Angular, but if you really want to execute your logic out of Angular, you need to get the rightzone
, as you have said.This trick is abusing Angular's dependency injection and hooking the injected
zone
onwindow
object, as this issue shows. Declaring a dependency onNgZone
, and assigning it towindow.zoneImpl
for exporting.After Angular bootstrapping, you should have a
zoneImpl
global variable. You can use therun
method to kick Angular off.zoneImpl.run(() => window.app.name = "new name!")
Live demo.