PadaKatel
PadaKatel

Reputation: 307

Angular 2 : View doesn't update when function is called from promise

My angular is pretty basic. I have a view where I display an object (which is in a service):

<div *ngFor="let group of service.groups">
    {{group.id}} - {{group.name}}
</div>

The simple version of my service looks like this:

public pushNewGroup(group) {

    this.groups.push(group);
    console.log('Pushing new group!');

    // this.zone.run(() => {
    //     this.groups.push(group);
    // });

}

public addGroup(group: Group) {
    let component = this;
    this.api.postWrapper('groups', group).then(function (data: Group) {
        component.pushNewGroup(data);
    });
}

If I create a button to call the service, everything works and the view updates:

<input type="button" (click)="pushGroup()" value="Add group/>

With service call in the view component:

pushGroup() {
    let group = { ... }
    this.service.pushNewGroup(group);
}

But if I call the promise through a dialog window then it doesn't update the view:

<li (click)="addGroup()" ><a>Add Group</a></li>

Component (simplified):

addGroup() {
    let dialogRef = this.dialog.open(AddGroupComponent, {
        data: {
            ...
        },
    });
}

export class AddGroupComponent {

    constructor(private service: service) {}

    addGroup(group: Group) {
        this.service.addGroup(group);
    }
}

I've tried both ngZone and ChangeDetectionStrategy.Default. Both solutions did not work for me. I can see that the object changes both times and the console log also works. But the view does not update.


My @Componment doesn't have anything interesting. For the whole class it's:

@Component({
    templateUrl: './mainComponent.html',
    styleUrls: ['./mainComponent.scss'],
    providers: []
})

And for my add group dialog it is:

@Component({
    selector: 'addGroup',
    templateUrl: './AddGroupComponent.html',
    styleUrls: ['./AddGroupComponent.scss'],
    providers: [ApiService, PermissionsService, Service],
    changeDetection: ChangeDetectionStrategy.Default
})

EDIT: It's very hard to extract the whole thing into plunker, but I tried recreating it and turns out the promise thing works. I think the fault might be with MatDialog. It doesn't update the main view. I tried recreating the whole thing in plunker, but I can't get angular material working in plunker. And it seems like all other examples on the net are broken as well:

https://embed.plnkr.co/LTAEwV6bNvoGQAFoky60/

Upvotes: 0

Views: 1806

Answers (2)

Christian Benseler
Christian Benseler

Reputation: 8075

Why don't you use arrow function and forget this hack let component = this? Maybe this can be the problem. Use the ES6 features, follow the angular styleguide.

public addGroup(group: Group) {
  this.api.postWrapper('groups', group).then( (data: Group) => {
     this.pushNewGroup(data);
  });
}

Upvotes: 1

Sanju
Sanju

Reputation: 1518

Promise will postpone the change detection to the next detection cycle.

Try this:

Add private _cdr: ChangeDetectorRef in the constructor.(obviously import ChangeDetectorRef)

Add this._cdr.detectChanges() inside promise (at the end).

Upvotes: 0

Related Questions