0

I have a service like so:

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';
import {AttachmentModel} from "../view-attachments/attachment.model";
@Injectable()
   export class AttachmentService {
   // Observable array sources
     private attachmentSource = new Subject<AttachmentModel>();

   // Observable array streams
   attachmentAdded$ = this.attachmentSource.asObservable();

   // Service commands
  addAttachment(attachment: AttachmentModel) {
     this.attachmentSource.next(attachment);
  }
}

and I call it from a component like so:

import {Component, OnInit, Input, ChangeDetectorRef, EventEmitter, Output} from '@angular/core';
import {AttachmentModel} from "./attachment.model";
import {AttachmentService} from "../services/AttachmentService";  

@Component({
   selector: 'view-attachments',
   templateUrl: './view.component.html',
   styleUrls: ['./view.component.css']
})
export class ViewComponent implements OnInit {
  public attachments;
  public attachment: AttachmentModel;

  constructor(private attachmentService: AttachmentService) {
    this.attachments = [];
  }

  ngOnInit() {
    this.attachmentService.attachmentAdded$.subscribe(
        attachments => {
            alert();
            this.attachments.push(attachments);
            this.attachments = this.attachments.slice();
        }
    );
}

handleGoogleFiles = (files) => {
    if (typeof(files) !== 'undefined') {
        for (let file of files) {
            this.attachmentService.addAttachment({
                deleted: false,
                resource_drive_file: file,
                resource_type: 'liveDrive',
                resource_drive_share_type: 'copy'
            });
        }
    }
 }
}

When I add an item to the service the alert fires as you would expect and so does the attachments.push.

However, the view is not updated until I click anywhere on the DOM and then any subsequent attachment additions show straight away.

What am I missing here?

2
  • Where do you call handleGoogleFiles? Are you sure that it is executed within angular zone? Commented May 8, 2017 at 13:51
  • Within the view I've got a call to a directive as so: <app-google-drive-picker (filesAdded)="handleGoogleFiles($event)"></app-google-drive-picker> , this directive emits an event when a file is selected from Google Drive Picker, the method handleGoogleFiles successfully receives the data from this directive Commented May 8, 2017 at 14:04

1 Answer 1

1

You can run a this.zone.run(() => {}); to trigger a redraw of the page.

zone is defined as follows

public zone: NgZone

You do not alter the variable by itself but changing the content of the variable. Its still on the same place in memory. At this point the change detections fails sometimes.

Sign up to request clarification or add additional context in comments.

3 Comments

I implemented it as follows: this.zone.run(() => { this.attachments.push(attachment); });
I would usually do it like this.zone.run(() => { }); this.attachments.push(attachment);
More the other way around: this.attachments.push(attachment); this.zone.run(() => { });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.