Выполните функцию, когда * ngFor закончил в angular 2
Я пытаюсь создать приложение с angular 2, я хочу, чтобы последний элемент отображался в * ngFor, выполните функцию, примерно так:
<ul>
<li *ngFor="#i of items">{{i.text}}</li> <==== i want when this is complete execute a functuon in my class
</ul>
Спасибо.
Ответы
Ответ 1
Update
Вы можете использовать @ViewChildren
для этой цели
Существует три случая
1. при инициализации ngFor
элемент не выделяется из-за ngIf
на нем или он родительский
- и в этом случае, когда
ngIf
станет правдивым, вы будете уведомлены подпиской ViewChildren
2. при инициализации ngFor
элемент раздается независимо от ngIf
на нем или он родительский
- и в этом случае подписка
ViewChildren
не будет уведомлять вас впервые, но вы можете быть уверены, что она отображается в ngAfterViewInit
hook
Элементы 3. добавляются/удаляются в/из ngFor
Array
- и в этом случае подписка
ViewChildren
сообщит вам
[демонстрация плунжера] (см. здесь журнал консоли)
@Component({
selector: 'my-app',
template: `
<ul *ngIf="!isHidden">
<li #allTheseThings *ngFor="let i of items; let last = last">{{i}}</li>
</ul>
<br>
<button (click)="items.push('another')">Add Another</button>
<button (click)="isHidden = !isHidden">{{isHidden ? 'Show' : 'Hide'}}</button>
`,
})
export class App {
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
@ViewChildren('allTheseThings') things: QueryList<any>;
ngAfterViewInit() {
this.things.changes.subscribe(t => {
this.ngForRendred();
})
}
ngForRendred() {
console.log('NgFor is Rendered');
}
}
.
Оригинальные
Вы можете сделать это так (но смотрите побочные эффекты для себя)
<ul>
<li *ngFor="let i of items; let last = last">{{i}} {{last ? callFunction(i) : ''}}</li>
</ul>
Что такое Бесполезно,, если оно не используется с changeDetectionStrategy.OnPush
Затем вы можете контролировать, сколько раз происходит изменение обнаружения, поэтому сколько раз вы вызываете свою функцию.
, т.е.. При изменении данных items
вы можете запустить следующий changeDetection
, и ваша функция даст правильную индикацию того, что ngFor
отображается для реального изменения. > .
Ответ 2
вы можете сделать то же самое, получив последний индекс, используя #last
of *ngFor
, и вызовите функцию, получив последнее значение индекса и сделайте все, что захотите. вот код для того же самого -
<ul>
<li *ngFor="#item of items; #last = last">
<span *ngIf='last'>{{hello(last)}}</span>
{{item}}
</li>
</ul>
items: Array<number> = [1,2,3,4,5]
constructor() { console.clear();}
hello(a){
if(a==true)
this.callbackFunction();
}
callbackFunction(){
console.log("last element");
}
рабочий пример для того же Рабочий планкер
Ответ 3
Я использовал небольшой взлом подхода, о котором другие жаловались, и он работал как шарм:
<ul>
<li *ngFor="let i of items; let last = last">{{i}} {{last ? callFunction(i) : ''}}</li>
</ul>
Затем в вашем компоненте:
shouldDoIt = true; // initialize it to true for the first run
callFunction(stuff) {
if (this.shouldDoIt) {
// Do all the things with the stuff
this.shouldDoIt = false; // set it to false until you need to trigger again
}
}
Это не касается корня проблемы с этим подходом, но это чрезвычайно дешевый хак, который заставил мое приложение работать плавно. Надеюсь, что команда Angular проведет более удобный способ запускать некоторый код после того, как * ngFor загрузит его содержимое.
Ответ 4
Я столкнулся с тем же вопросом и нахожу один способ обойти это. Не уверен, подходит ли он вам или нет.
Предварительные условия: вы используете ngFor для визуализации входящих свойств.
context: Мне нужно вызвать MDL upgradeAllRegistered, чтобы сделать checkbox довольно после получения данных сетки из back-end.
Я добавляю один setTimeout внутри 'ngOnChanges';
grid.componet.ts:
export class GridComponent {
@Input() public rows: Array<any>;
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
for (let propName in changes) {
if (propName == 'rows') {
setTimeout(() => componentHandler.upgradeAllRegistered());
}
}
}
}
grid.component.html:
<tr #rowDOM *ngFor="let row of rows;"></tr>
Ответ 5
Я столкнулся с этой проблемой. В моем случае я вызывал веб-службу для извлечения данных и должен был выполнить javascript для инициализации каждого шаблона, созданного *ngFor
. Вот что я придумал:
updateData() {
this.dataService.getData().subscribe(
function(data) {
this.data = data;
setTimeout(javascriptInitializationFunction, 0);
},
function(err) { /* handle it */ }
);
}
setTimout
будет ожидать обновления DOM перед выполнением. Это не совсем то, что вы просили, но, надеюсь, это помогает.
Ответ 6
Мне удалось выполнить некоторые хаки, чтобы предотвратить событие get triggred (я обнаружил, что прокрутка всегда вызывает эти события)
Добавив: [Добавить в свой компонент]
private globalFlag = -1;
и это мое событие, которое будет запущено при завершении цикла
ev(flag){
if(flag != this.globalFlag){
console.log("TRIGGER!")
this.globalFlag = flag;
}
}
и этот код цикла
<div *ngFor="let var of list;let i=index;let last=last">
{{last ? ev(i) : ''}}
</div>
Основная идея состоит в том, чтобы предотвратить запуск события, если флаг был таким же. Так что это только триггер, когда значение globalFlag отличается текущим флагом, который прошел от ngFor. Извините за мой плохой английский, надеюсь, что вы поймете мою идею.