9

How do I let Angular propagate the changes i did to the model. In AngularJS this would be really easy, but i cannot seem to get it working in Angular. I know the entire change detection system and view propagation is changed entirely. Somehow, i need to inform angular of the changes. But how can i do this in practise.

See this piece of typescript code:

import {Component, View, bootstrap, For} from 'angular2/angular2';

// Annotation section
@Component({
    selector: 'app'
})
@View({
    template: `
    <div *for="#user of users">
        {{user}}
    </div>
    `,
    directives: [For]
})
class App {
    users:Array<String>;

    constructor() {
        this.users = [];
        this.fillUsersAsync();
    }

    fillUsersAsync(){
        window['fetch']('http://jsonplaceholder.typicode.com/users')
            .then( resp => resp.json())
            .then( users => users.forEach(user => this.users.push(user.name)))
            .then( () => console.log('Retrieved users and put on the model: ', this.users));
    }
}

bootstrap(App);

You will see that, after the users get loaded into the model, the view doesn't update.

I'm using systemjs 0.16, angular 2.0.0-alpha.23.

See this plnkr for the example (currently, works only in chrome, as the new 'fetch' api is used)

nicojs
  • 1,879
  • 2
  • 18
  • 34

4 Answers4

2

I found the issue. Apparently, its a bug to be fixed in alpha 27. See this bug report: https://github.com/angular/angular/issues/1913

Angular2 uses zonejs to know when to start the digest cycle (the dirty checking and update the view). As of now, zonejs is not triggered after fetching data with the new window.fetch().

Replacing the window['fetch'] line to this fixed the issue for me: Zone.bindPromiseFn(window['fetch'])('http://jsonplaceholder.typicode.com/users')

nicojs
  • 1,879
  • 2
  • 18
  • 34
1

To update data at view in AngularJS2 you should use Forms. You can read about this at this page or see more details here. If I understand Forms correctly, you should modify yout @View part like this:

@View({
    template: `
    <div *for="#user of users" control="users">
        {{user}}
    </div>
    `,
    directives: [For]
})

--edited

Try this:

import {Component, View, bootstrap, For} from 'angular2/angular2';

// Annotation section
@Component({
    selector: 'app'
})
@View({
    template: `
    <div [control]="users" *for="#user of users">
        {{user.value}}
    </div>
    `,
    directives: [For, forms]
})
class App {
    users:Array<String>;

    constructor() {
        this.users = new Control([]);
        this.fillUsersAsync();
    }

    fillUsersAsync(){
        window['fetch']('http://jsonplaceholder.typicode.com/users')
            .then( resp => resp.json())
            .then( users => 
                var usersArr = []
                users.forEach(user => 
                      usersArr.push(user.name))
                this.users = new Control(usersArr));
        }
 }

 bootstrap(App);

I am not sure that my answer is totally correct, but I can't find more information. Experiment with this code and may the Force be with you! :)

Also I found this link, very informative.

As I understand, when in constructor you should initialize youre users variable via new Control(some data) and then, in view template you can access to this data like this - {{users.value}}.

If it does not work: try the same but with very simple data, e.g. use string instead of an array.

And this video will helps to unserstand forms in ng2.

ndsmyter
  • 6,535
  • 3
  • 22
  • 37
Vladyslav Sheruda
  • 1,856
  • 18
  • 26
  • Your second link seems to put me on the right path, but the document seems to be out-dated. I think i need some kind of form directive in the directives array, but what is the name, and how to import it? – nicojs Jun 05 '15 at 09:31
  • @nicojs would advise to do as in the example of the first link and if it not work, do like in the second. The directive name for `forms` - directives: [forms] or maybe [Forms]. Import it like you import [For] directive. Try this and report please, I try to help you more. – Vladyslav Sheruda Jun 05 '15 at 09:36
  • I tried it all, but it is not working. I think we're looking in the wrong direction. As far is I know, angular2 still uses dirty checking to see if the model is changed. Somehow i need to inform angular2 that i updated the model. Or use a $http equivalent. – nicojs Jun 06 '15 at 14:01
  • I think we missed something... it's must work with [control] statement. I edit my answer in few minutes. Check it, please. – Vladyslav Sheruda Jun 06 '15 at 17:30
0

Just answered it here Angular2 View Not Changing After Data Is Updated

Basically, there was a bug in Beta 2.0.0-beta.1.

Hope it helps!

Community
  • 1
  • 1
Alan Wagner
  • 2,230
  • 1
  • 16
  • 13
-2

Ng-prefixes are back. For has now become ngFor for Angular2 versions alpha-24+.

import {NgFor} from 'angular2/directives';
@View({
  directives: [ngFor]
})

Then use *ng-for=#user of users" in the template.

Checkout the ngFor docs or a working example

shmck
  • 5,129
  • 4
  • 17
  • 29
  • The problem is not For, it is working correctly. That is why i specified that i am using alpha-22. But at the time angular2 is evaluating the view, the users array is still empty. The problem is that angular2 is not informed of the changes in the model after the fetch is done. As far is i know, angular2 is not using Object.observe, but still uses dirty checking to check for changes. So it does not know about the changes in the view. In angular 1.x you would be using $http, or even $apply. Is there an angular2 equivalent? – nicojs Jun 06 '15 at 13:55
  • With alpha-code you might want to consider sticking to the latest version to avoid more bugs and incomplete features. In Angular2 there is no $apply, nor is it necessary, the view should just update based on the model. Instead of $http, you can use any request method in ng2. See [this response](http://stackoverflow.com/questions/28910864/angular-2-how-to-use-import-the-http-module) from Angular's creator. – shmck Jun 06 '15 at 23:43
  • Ok, no $apply needed. But there has to be some way to inform the change detection of my changes. It will not poll for it, nor is it using Object.observe. So how do i fix this? – nicojs Jun 10 '15 at 15:10
  • There actually is: `_ngZone.run()`. See https://angular.io/docs/js/latest/api/core/NgZone-class.html – rnons Oct 23 '15 at 08:41