0

I have a simple angular2 (rc1) component which subscribes to a service. When the service updates the subscription, I can log the result in the component's subscription but the view isn't updated.

My initial suspicion was that my inner this wasn't bound to the outer one, but I'm using a fat arrow on the subscribe callback, and also tried the old let self = this on the first line of the constructor and then doing self.SuccessMessage = result to no avail.

Do I have to force the change detection somehow? Here's my component:

import {Component} from 'angular2/core';
import {Subscription} from 'rxjs/Subscription';

import {UploaderService} from './uploader.service';

@Component({
  selector: 'aoma-uploader-status-mini',
  providers: [],
  viewProviders: [],
  templateUrl: './app/uploader/mini-uploader-status.component.html'
})
export class MiniUploadStatusComponent {
  subscription:Subscription;
  successMessage:any = {};

  constructor(private _uploaderService: UploaderService) {
    // view correctly shows this value:
    this.successMessage.serverMessage = 'before ';
    this.subscription = _uploaderService.fileSuccess$.subscribe(result => {
        // this fires and logs the result correctly:
        console.log('the mini uploader: type of result', result);
        // view is never updated here
        this.successMessage = result;
      })
  }

}

Currently my view only has {{ successMessage | json }} in it. Again it correctly displays the 'before' value, but doesn't change when the subscription gets the result object.

Fiona
  • 1,211
  • 3
  • 16
  • 20

1 Answers1

3

It looks like _uploaderService runs outside Angulars zone. Angular won't detect changes when values are changed from outside its zone.

To make the code to run inside the zone use

  constructor(private _uploaderService: UploaderService, private zone:NgZone) {
    // view correctly shows this value:
    this.successMessage.serverMessage = 'before ';
    this.subscription = _uploaderService.fileSuccess$.subscribe(result => {
        // this fires and logs the result correctly:
        console.log('the mini uploader: type of result', result);
        // view is never updated here

        this.zone.run(() => this.successMessage = result);
      })
  }

There are also other ways to notify Angular about changes Manual Change Detection in AngularJS or Angular 2?

If there is additional code run like when router.navigate() is called outside the zone, only zone.run(...) will properly solve the issue - except when there is a way to make your service run inside Angulars zone in the first place.

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • If this doesn't help more information is required like the part of your template that shows how you bind to the `successMessage`. – Günter Zöchbauer May 04 '16 at 14:04
  • Thanks for the answer; I've updated the question to show my template content. Unfortunately zone.run(...) didn't work. I'm thinking I should look into `ChangeDetectionStrategy`? Of course if you have an example that would be great ;-). – Fiona May 04 '16 at 14:51
  • If `zone.run` didn't solve it, the problem is caused by something else. Can you post what `console.log('the mini uploader: type of result', result.json());` prints to the console? – Günter Zöchbauer May 04 '16 at 14:56
  • It prints was I was hoping, which is an object with the server response: `the mini uploader: type of result object Object {file: ResumableFile, serverMessage: "Thank you for uploading to the server."}` – Fiona May 04 '16 at 15:33
  • When you add this to `successMessage` statically, does it show it? It's quite weird. Everything looks fine ... – Günter Zöchbauer May 04 '16 at 15:37
  • thanks. When I set it statically the view did indeed change. In the end, the issue was that the JSON pipe was silently not outputting the object, mostly likely because it contained a FileReader object. Doh! Thanks for your help! – Fiona May 07 '16 at 12:21
  • Is this solution still valid? – Devesh Jadon Apr 06 '18 at 18:36
  • @DeveshJadon yes, it is – Günter Zöchbauer Apr 06 '18 at 21:04