Angular 6 refresh array and ngFor in template

Viewed 3042

I use angular 6 and I have a ngbCarousel that I want to add photos with a click of a button.

I use ngFor to create the HTML of the carousel.

<ngb-carousel #carousel *ngIf="images">
  <ng-template ngbSlide *ngFor="let im of images; let i = index">
    <img [src]='im.link' >
    <div>
      <input type="text" value={{im.name}} >    
      <input type="text" value='description of img' >    
      <input type="text" value='copyright owners' >          
      <button type="button" (click)='deletepic(i)'>delete</button>   
    </div>
  </ng-template>
</ngb-carousel>

<button type="button" (click)='addpic()'>add</button> 
<button type="button" (click)='last()'>last</button> 

The images array that contains JSON is this images= [{'link':'https://picsum.photos/900/500/?image=5','name':'first'},{'link':'https://picsum.photos/900/500/?image=574','name':'second'},{'link':'https://picsum.photos/900/500/?image=547','name':'third'}]; and when the addpic is clicked, another json is added in the array.

 addpic(){
    this.images.push({'link':'https://picsum.photos/900/500/?image=7','name':'added one'});     
      this.last()        ;   
  }

Also it has to force carousel to show the last, newly added photo. According to the API I have to use the select to navigate to a slide by its id, and the id is of the pattern ngb-slide-0.

So, last contains

  last(){
    let slide = 'ngb-slide-'+String(this.images.length-1);    
    this.carousel.select(slide); 
  }

The last photo is normally added to the carousel

The problem is that the last will not work when called from the addpic. It never goes to the last photo, even if the photo is added. If I put the

let slide = 'ngb-slide-'+String(this.images.length-1);    
this.carousel.select(slide); 

of last in the addpic will still not work. It always goes to the second to last photo (if I have 3 photos it always goes to the 3rd, after adding a 4th)

But this will work if I hit the last button or if I use the arrows in the carousel UI.

This makes me think that somehow the HTML or the array are not "refreshed" when the last is called in the typescript, but somehow the buttons refresh/create the HTML needed to show the right photo?

I dont know what it is, but I am almost certain now it has to do with html/typescript being refreshed. I think this is an angular issue and not a ngbCarousel issue. I dont know how to debug or proceed.

Please advice. Thanks

2 Answers

After adding picture in array in addpic() method they take bit time to reflect in html as template so call last method in timeout like

addpic(){
    this.images.push({'link':'https://picsum.photos/900/500/?image=7','name':'added one'});     
    setTimeout(() => {
        this.last();
    });
  }

You can use setTimeout to force the last method being executed after the changes has been detected by Angular, as in Paresh Gamis's answer.

But I think you could also use ChangeDetectorRef.detectChanges() in this situation, it feels less "hacky". (Documentation, and related Q&A here : What's the difference between markForCheck() and detectChanges() )

use it just before your last call.

I am not sure if it will work in your case (if you provide a StackBlitz minimal example, we could work on the details)

Related