Em Angular 1, escrevi uma diretiva personalizada (“pronto para repetidor”) para usar com ng-repeat
para invocar um método de retorno de chamada quando a iteração foi concluída:
if ($scope.$last === true) { $timeout(() => { $scope.$parent.$parent.$eval(someCallbackMethod); }); }
Uso na marcação:
Como posso obter uma funcionalidade semelhante com o ngFor
no Angular 2?
Você pode usar algo assim ( ngPara variables locais ):
Então você pode Interceptar alterações de propriedade de input com um setter
@Input() set ready(isReady: boolean) { if (isReady) someCallbackMethod(); }
Você pode usar @ViewChildren para essa finalidade
@Component({ selector: 'my-app', template: ` - {{i}}
`, }) export class App { items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; @ViewChildren('allTheseThings') things: QueryList; ngAfterViewInit() { this.things.changes.subscribe(t => { this.ngForRendred(); }) } ngForRendred() { console.log('NgFor is Rendered'); } }
Resposta original está aqui https://stackoverflow.com/a/37088348/5700401
Para mim funciona em Angular2 usando o Typescript.
... {{ngForCallback()}}
Então você pode manipular usando esta function
public ngForCallback() { ... }
Em vez de [ready], use [attr.ready] como abaixo
Eu encontrei no RC3 a resposta aceita não funciona. No entanto, encontrei uma maneira de lidar com isso. Para mim, preciso saber quando o ngFor acabou de executar o componente MDLHandler para atualizar os componentes.
Primeiro você precisará de uma diretiva.
upgradeComponents.directive.ts
import { Directive, ElementRef, Input } from '@angular/core'; declare var componentHandler : any; @Directive({ selector: '[upgrade-components]' }) export class UpgradeComponentsDirective{ @Input('upgrade-components') set upgradeComponents(upgrade : boolean){ if(upgrade) componentHandler.upgradeAllRegistered(); } }
Em seguida, importe isso para o seu componente e adicione-o às diretivas
import {UpgradeComponentsDirective} from './upgradeComponents.directive'; @Component({ templateUrl: 'templates/mytemplate.html', directives: [UpgradeComponentsDirective] })
Agora, no HTML, defina o atributo “upgrade-components” como true.
Quando esse atributo é definido como true, ele executará o método na declaração @Input (). No meu caso, ele executa o componentHandler.upgradeAllRegistered (). No entanto, ele poderia ser usado para qualquer coisa de sua escolha. Vinculando-se à propriedade ‘last’ da instrução ngFor, isso será executado quando terminar.
Você não precisará usar [attr.upgrade-components] mesmo que este não seja um atributo nativo, já que agora é uma diretiva genuína.
Eu escrevo uma demonstração para este problema. A teoria é baseada na resposta aceita, mas esta resposta não está completa porque o li
deve ser um componente personalizado que pode aceitar uma input ready
.
Eu escrevo uma demonstração completa para este problema.
Defina um novo componente:
import {Component, Input, OnInit} de ‘@ angular / core’;
@Component({ selector: 'app-li-ready', templateUrl: './li-ready.component.html', styleUrls: ['./li-ready.component.css'] }) export class LiReadyComponent implements OnInit { items: string[] = []; @Input() item; constructor() { } ngOnInit(): void { console.log('LiReadyComponent'); } @Input() set ready(isReady: boolean) { if (isReady) { console.log('===isReady!'); } } }
modelo
{{item}}
uso no componente de aplicativo
Você verá que o log no console imprimirá toda a sequência de itens e depois imprimirá o isReady.
A solução é bastante trivial. Se você precisar saber quando o ngFor
concluir a impressão de todos os elementos DOM na janela do navegador, faça o seguinte:
Adicione um espaço reservado para o conteúdo que está sendo impresso:
Crie um contêiner com display: none
para o conteúdo. Quando todos os itens são impressos, display: block
. contentPrinted
é uma propriedade de sinalizador de componente, cujo padrão é false
:
Adicione onContentPrinted()
ao componente, que se desativa depois que ngFor
concluído:
onContentPrinted() { this.contentPrinted = true; this.changeDetector.detectChanges(); }
E não esqueça de usar ChangeDetectorRef
para evitar ExpressionChangedAfterItHasBeenCheckedError
.
last
valor Declare a last
variável no ngFor
. Use-o dentro de li
para executar um método quando este item for o último :
contentPrinted
para executar onContentPrinted()
apenas uma vez . ng-container
para não causar impacto no layout. Como chamar a function “navegar” do retorno de chamada com params? Eu tenho algo assim:
Eu ainda não olhei em profundidade como ngFor processa elementos sob o capô. Mas a partir da observação, notei que muitas vezes ele tende a avaliar expressões mais de uma vez para cada item que está interagindo.
Isso faz com que qualquer chamada do método datilografado seja feita ao verificar a variável ‘last’ do ngFor, algumas vezes, acionada mais de uma vez.
Para garantir uma única chamada ao seu método datilografado por ngPara quando terminar adequadamente a iteração através de itens, você precisará adicionar uma pequena proteção contra a reavaliação de várias expressões que o ngFor faz sob o capô.
Aqui está uma maneira de fazer isso (através de uma diretiva), espero que ajude:
O código da diretiva
import { Directive, OnDestroy, Input, AfterViewInit } from '@angular/core'; @Directive({ selector: '[callback]' }) export class CallbackDirective implements AfterViewInit, OnDestroy { is_init:boolean = false; called:boolean = false; @Input('callback') callback:()=>any; constructor() { } ngAfterViewInit():void{ this.is_init = true; } ngOnDestroy():void { this.is_init = false; this.called = false; } @Input('callback-condition') set condition(value: any) { if (value==false || this.called) return; // in case callback-condition is set prior ngAfterViewInit is called if (!this.is_init) { setTimeout(()=>this.condition = value, 50); return; } if (this.callback) { this.callback(); this.called = true; } else console.error("callback is null"); } }
Depois de declarar a diretiva acima em seu módulo (supondo que você saiba como fazer isso, se não, pergunte e esperamos que atualize isso com um trecho de código), aqui está como usar a diretiva com ngFor:
{{item}}
‘doSomething’ é o nome do método no seu arquivo TypeScript que você deseja chamar quando ngFor finaliza a iteração pelos itens.
Nota: ‘doSomething’ não tem colchetes ‘()’ aqui, pois estamos apenas passando uma referência ao método typescript e não estamos chamando isso aqui.
E finalmente aqui está como o método ‘doSomething’ se parece no seu arquivo datilografado:
public doSomething=()=> { console.log("triggered from the directive's parent component when ngFor finishes iterating"); }