Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call a function after completing the *ngFor

Tags:

angular

ngfor

I'm trying to create a application with angular 2; I want when last element rendered in *ngFor,execute a function, something like this, tag is <img>:

<img *ngFor="let image of template.previewImages; let i = index" [src]="image" [class.hs_visible]="i==0" />

Function name is

animation(){console.log('enter');}
like image 900
Bhawna Avatar asked Oct 01 '16 04:10

Bhawna


2 Answers

See this Plunker for the solution I managed to come up with.

It might not be elegant, but it (mostly) works!

Basically, *ngFor helpfully provides a handful of values, like index, even, odd, and fortunately enough, first and last booleans that evaluate to true for the respective iterations. First, you have to expose the values as local variables in the *ngFor exactly as you would the index. Then, you have to get Angular to call the function from the template, which you can do as if you were binding a value to the template but with a tertiary conditional (that returns null for false evaluations).

<div *ngFor="let i of stuff; let l = last ">
  {{ i }} {{ l === true ? callOnLastIteration() : null}}
</div>

I say "(mostly) works" because it seems that if you try to bind to a property inside of the *ngFor-ed element, other than the one you are iterating on and then change value of said property inside of the function called at the last iteration, you'll get undesired behavior and errors from Angular's change propagation system. See the Plunker for details.

like image 171
ABabin Avatar answered Sep 18 '22 11:09

ABabin


It would be better if you can create a directive which will do the same. You just need to pass the last flag to directive and it will call desired function when last element gets rendered.

View

<p class="my-element" 
  *ngFor="let i of stuff; let l = last" 
  [lastElement]="l" (lastFunc)="test()">
    {{i}}
</p>

Directive

import { Directive, ElementRef, Input, Output, EventEmitter } from '@angular/core';

@Directive({
  selector: '[lastElement]'
})
export class LastElementDirective {
  @Input() lastElement : any;
  @Output() lastFunc = new EventEmitter();
  constructor(private el: ElementRef) { 
    this.setTimer(); //somehow lastElem value is available on next tick
  }
  setTimer(){
    setTimeout(() => {
      if(this.lastElem) this.lastFunc.emit();
    }, 0);    
  }
}

Plunkr in action

like image 45
Pankaj Parkar Avatar answered Sep 22 '22 11:09

Pankaj Parkar