Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 UI not updating when items added to array on image.onload()

I am attempting to add images to an array and display them on the screen. I do not want to display the images until after the browser has loaded them. I have .onload call back specified on the image object and am adding the image to the array within that callback. The UI is only updated when a click event or some other "change event" happens. I looked in to observables but feel like thats a bit overkill for something this simple. I believe in angular 1 there was some sort of $watch that could be done to class properties. This seems trivial... object gets updated, UI should reflect it. Any help is appreciated. Thanks :)

Here is a plunker demonstrating what I am trying to do. I am adding X kittens in the constructor. If that code is removed, the first "Add Kittens" press will not update the UI but subsequent additions of kittens will show previous kittens...

private addItem(itemsArray) { 
    var randomnumber = Math.floor(Math.random() * (500 - 200 + 1)) + 200;  
    var imageObj = new Image();
    imageObj.src = "http://placekitten.com/300/"+randomnumber;

    imageObj.onload = function () {       
        itemsArray.push(imageObj);
    }
}
like image 992
crizzwald Avatar asked Jun 23 '16 00:06

crizzwald


Video Answer


1 Answers

I can't reproduce in the Plunker (with Chrome)

You could try to explicitly invoke change detection

export class App {
  public items: any = []
  constructor(cdRef:ChangeDetectorRef) { // <<<== add parameter
    this.addItems();
  }

  addItems() {
    for(var i = 0; i < 3; i++)
    {
      this.addItem(this.items);
    }
  }

  private addItem(itemsArray) { 
    var randomnumber = Math.floor(Math.random() * (500 - 200 + 1)) + 200;  
    var imageObj = new Image();
    imageObj.src = "http://placekitten.com/300/"+randomnumber;

    imageObj.onload = () => { // <<<== change from function() to () =>     

        itemsArray.push(imageObj);
        this.cdRef.detectChanges(); // <<<== invoke change detection
        //alert("added");
    }
  }
}

My suspicion is that

imageObj.onload = () => {

can't be properly patched on all browsers and if the callback runs outside Angulars zone, it doesn't get notified and doesn't run change detection.

This

imageObj.addEventListener('load', () => {       

might also solve it (and would be the better option if it solves it as well - hard to tell without being able to reproduce - I have no Safari around).

Plunker example

like image 174
Günter Zöchbauer Avatar answered Sep 27 '22 19:09

Günter Zöchbauer