在* ngFor以角度2

时间:2016-05-07 11:16:32

标签: javascript angular

我尝试用角度2创建一个应用程序,我想在* ngFor中渲染最后一个元素时,执行一个函数,像这样:

<ul>
  <li *ngFor="#i of items">{{i.text}}</li> <==== i want when this completed, execute a functuon in my class
</ul>

感谢。

7 个答案:

答案 0 :(得分:46)

更新

您可以将@ViewChildren用于此目的

有三种情况

初始化ngFor元素上的

1。由于ngIf或其父级

而不是rendred
  • 在这种情况下,当ngIf变得真实时,ViewChildren订阅
  • 会通知您
初始化ngFor元素上的

2。是rendred,无论其上是ngIf还是它的父级

  • 在这种情况下ViewChildren订阅不会第一次通知您,但您可以确定它是在ngAfterViewInit挂钩
  • 中呈现的

3。ngFor数组

中添加/删除项目
  • 在这种情况下,ViewChildren订阅也会通知您

[Plunker Demo] (请参阅控制台日志)

@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');
  }
}

原始

您可以这样做(但请参阅the side Effects for yourself

<ul>
  <li *ngFor="let i of items; let last = last">{{i}} {{last ? callFunction(i) : ''}}</li>
</ul>

除非与changeDetectionStrategy.OnPush

一起使用,否则无用,

然后,您可以控制更改检测的次数,从而控制您的函数被调用的次数。

ie: changeDetection的数据发生变化时,您可以触发下一个items,并且您的函数会正确指示{{1}为真实更改呈现。

答案 1 :(得分:4)

我使用了其他人抱怨的方法,它就像一个魅力:

SELECT a1.userid,
   SUM(path="abc.com") as is_CWS,
   a2.Apply_num,
   is_CWS/a2.Apply_num FROM
TABLE
JOIN
(select userid,count(userid) as Apply_num
FROM TABLE
where trackid is not NULL
group by userid) a2 
on a1.userid=a2.userid
GROUP BY userid

然后在你的组件中:

GROUP BY

这并没有解决这种方法的问题根源,但它是一个极低成本的黑客,使我的应用程序运行顺利。我希望Angular团队能够在* ngFor加载其内容后实现更友好的方式来触发一些代码。

答案 2 :(得分:2)

你可以通过使用#last的{​​{1}}来获取最后一个索引,并通过获取最后一个索引值来调用函数,并根据需要执行任何操作。这是相同的代码 -

*ngFor

相同 Working Plunker

的工作示例

答案 3 :(得分:2)

我也遇到了这个问题。就我而言,我正在调用一个Web服务来检索数据,并且需要执行javascript来初始化*ngFor生成的每个模板。这就是我想出的:

updateData() {
  this.dataService.getData().subscribe(
    function(data) {
      this.data = data;
      setTimeout(javascriptInitializationFunction, 0);
    },
    function(err) { /* handle it */ }
  );
}

setTimout将等待DOM在执行之前进行更新。这不完全是你提出的要求,但希望它有所帮助。

答案 4 :(得分:1)

我面临同样的问题,找到一种方法来解决这个问题。不确定它是否适合你。
前提条件是您使用ngFor来呈现入站属性。

context:我需要调用MDL的upgradeAllRegistered,以便在从后端获取网格数据后使复选框变得非常漂亮。

我在'ngOnChanges'中添加了一个setTimeout;

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 :(得分:1)

我设法执行一些黑客攻击以防止事件被触发(我发现滚动总是触发那些事件)

添加:[在您的组件中添加]

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传递的当前标志不同时才会触发。抱歉我的英语不好,希望你能理解我的想法。

答案 6 :(得分:0)

可能的解决方案:答案显示在https://stackblitz.com/edit/angular-phpauq?file=src%2Fapp%2Fapp.component.ts

app.component.html

<div [innerHTML]="html"></div>

app.component.ts

 html = '';
ngAfterViewInit(){
       let  i;
       this.html += '<ul>';
       for(i = 0 ; i < this.abc.length ; i++){
           this.html += '<li>';
           this.html +=  this.abc[i];
           if(parseInt(i) === this.abc.length - 1){
           this.callMethod(i);
           }
           this.html += '</li>';
           }
           this.html += '</ul>';
    }


    callMethod(text){
    alert(text);
    }