Call a function after completing the *ngFor
Asked Answered
E

3

7

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');}
Elidiaelie answered 1/10, 2016 at 4:51 Comment(0)
V
3

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.

Voile answered 1/10, 2016 at 6:43 Comment(0)
L
1

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

Loincloth answered 1/10, 2016 at 8:50 Comment(0)
O
0

Pankay Parkar answer works, but you need to change the writing of lastElement in setTimeout function (now is lastElem, so the plunker doesn't work to check if is last element of *ngFor)

Ocreate answered 16/11, 2017 at 16:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.