Reacting to changes made outside of Angular2

I’ve got a non-angular page made with fairly basic JS, and thought it’d be a splendid idea to try and add learn some Angular2 and use it for some new functionality.

My plan was that I’d bind an Angular2 component to an object that is being updated by the old code, and I’d use Angular2 magic to update a chunk of UI.

The problem is I cant convince Angular2 to react to any changes made in the outside JS. What the trick to doing that? Attempts at googling the problem lead to in depth explanations of Angular2’s change detection process, which hasn’t been helpful so far. Is this just an awful idea?

I found a random Angular2 jsfiddle and hacked it up to show the problem. Strings are added to ‘window.names’, but you dont see them until one is added from the angular side: https://jsfiddle.net/byfo3jg3/ . The code follows:

var names = ['Joe'];

setTimeout(function() {
  names.push("Frank");
}, 1000);

setTimeout(function() {
  names.push("Sterve");
}, 2000);

setTimeout(function() {
  names.push("Garfield");
}, 3000);

(function() {
  var HelloApp,
        ListThing;

    ListThing = ng
        .Component({
            selector: 'list-thing',
            template: '<ul><li *ng-for="#name of names">{{name}}</li></ul>',
            directives: [ng.NgFor]
        })
        .Class({
            constructor: function() {
                this.names = window.names;

        setTimeout(function() {
                    this.names.push("Oh hai");
                }.bind(this), 10000);
            }
        });

    HelloApp = ng
        .Component({
            selector: 'hello-app',
            template: '<list-thing></list-thing>',
            directives: [ListThing]
        })
        .Class({
            constructor: function() {}
        });

    document.addEventListener('DOMContentLoaded', function() {
        ng.bootstrap(HelloApp);
    });
}());

3
Leave a Reply

avatar
3 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Jason Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jason
Guest

names should be component property to work inside of template:

constructor(){this.names = window.names}

Changes to window.names will not be detected by angular, so you have few options: poll names using setInterval(()=>{this.names = window.names}, 1000) or expose global callback:

constructor(zone:NgZone) 
{
   window.notify = ()=> {
        zone.run(()=> { 
                this.names = window.names;
        });
   }
 }

and call it from plain js window.notify() or use other methods to invoke change detection.

Jason
Guest

You will need to set the NgZone to window object and then call run function of the zone.

Please refer to Angular 2 How to get Angular to detect changes made outside Angular? SO Question

Jason
Guest

Is this just an awful idea? Yes. Angular’s automatic change detection system assumes that changes to data (that you want your components to display) are happening inside an event handler that is monkey-patched by Zone.js. Because then Angular’s change detection will execute when such an event handler fires (well, technically, it will execute after the event handler finishes). If you want a component view to automatically update, you have to change the bound data inside Angular – inside the Angular zone. As @Jigar answered, you can modify your code to call angularZone.run(_ => // make changes here), but if you… Read more »