Подтвердить что ты не робот

Выполните функцию, когда * 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>

Спасибо.

4b9b3361

Ответ 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. Извините за мой плохой английский, надеюсь, что вы поймете мою идею.