【问题标题】:Call a function inside ngFor in angular2在 angular2 中调用 ngFor 内部的函数
【发布时间】:2026-01-13 09:20:06
【问题描述】:

您好,我正在使用 Angular2,并且想获取服务器并为我在 ngFor 中获得的每个 ID 获取一些值。

<div *ngFor="let item in items">
  <span> here call a function that do something with 'item' and return something new <span>
</div>

【问题讨论】:

  • 听起来是个奇怪的要求。你想完成什么?
  • @Günter Zöchbauer 例如,以某种复杂的方式生成项目属性的显示名称。这一点也不奇怪。
  • 在代码中执行并将其分配给每个item,然后在*ngFor 中使用它。不鼓励从模板绑定中调用此类函数。
  • @GünterZöchbauer 你有没有机会分享一个正确方法的例子?
  • 这根本不是一个奇怪的要求,在项目创建上操作数据显然不是由 Angular 团队实现的任务。

标签: angular


【解决方案1】:

您可以使用自定义指令来调用每次迭代的方法:

import { Directive, Output, EventEmitter, Input, SimpleChange} from '@angular/core';

@Directive({
  selector: '[onCreate]'
})
export class OnCreate {

  @Output() onCreate: EventEmitter<any> = new EventEmitter<any>();
  constructor() {}
  ngOnInit() {      
     this.onCreate.emit('dummy'); 
  } 

}

然后你可以在你的 *ngFor 中使用它来调用你组件中的方法:

<div *ngFor="let item of items">
    <div *ngIf="item" (onCreate)="yourMethod(item)"> 
    </div>
</div>

在您的组件中,您可以将此方法称为:

yourMethod(item){
   console.log(item);
}

【讨论】:

  • 此代码是否需要更新才能与 Angular 6 兼容?我不能让它按原样工作。该函数永远不会被调用。我不得不重命名一些东西以使 TSLint 也允许我的应用程序编译。 OnCreate/onCreate需要重命名为NgForOnCreateDirective/ngForOnCreateDirective并且选择器必须以app为前缀,所以我将其改为appNgForOnCreate
  • @Routhinator,这个示例是否适用于 Angular 5?导致被调用的函数不起作用。 PS:我通过 CallFnDirective 将 onCreate 和选择器更改为 '[appCallFn]'。
【解决方案2】:

听起来不太好,但是,最简单的方法:

<div *ngFor="let item of items">
  <span data-dummy="{{myFunction()}}" > here call a function that do something with 'item' and return something new <span>
</div>

正确方法:

@Directive({
  selector: '[runDummyFunc]'
})
export class runDummyFunc {

  constructor() {}
  ngOnInit() {      
     this.runDummyFunc()
  } 

}


<div *ngFor="let item in items">
    <span [runDummyFunc]="myFunction" > here call a function that do something with 'item' and return something new <span>
</div>

在你的课堂上:

      myFunction = ():void=>{

         console.log('whatever');
      }

【讨论】:

  • 使用插值调用函数不是真正的方法,因为它会因为ngOnChanges而被多次调用。 @xe4me
  • @BhushanGadekar ,我知道这不是一个好方法,这就是为什么我说听起来不好,但这就是他想要的,他可以轻松地创建一个像 fire_once 这样的变量并设置如果它被调用一次就为真,无论如何,这不是一个好方法
【解决方案3】:

Typescript 本身中*ngFor 之前更改数据,

this.items.forEach((item,index)=>{
  item=this.func(item,index);
})

func(item,index):string{
    return item+ String(index); //do whatever you wish to do.
}

【讨论】:

  • 我尝试在订阅函数中执行此操作,但是我找不到访问我试图在 forEach 中创建的this.newArray 的方法。你能用一个例子来更新一下吗?
【解决方案4】:

在component.html的span标签之间再写一个“ngFor”

 <div *ngFor="let item in items">  
    <span *ngFor="let new of filterItems(item)"> {{new.anyAttribute}} </span>
 </div>

在component.ts中 如果你想过滤项目

filterItems(item) {
  let filterArray:any=[];
  return filterArray.filter(x => x.anyAttribute == item.anyAttribute);
}

如果你想在item中返回一个数组

filterItems(item){
   return item.Array //Array is an array in item
}

【讨论】:

    【解决方案5】:

    不确定这是否是您所要求的,但您可以将项目与这样的事件变量一起传递给函数:

    <div *ngFor="let item in items">
      <span (click)="functionCall($event, item)"> <span>
    </div>
    

    然后像这样在您的班级中抓取该项目:

    functionCall(event, item): void {
      console.log('item clicked:", item)
    }
    

    【讨论】:

      【解决方案6】:
      Component({
          selector:'heroes',
          template: `
          <table>
              <thead>
                  <th>Name</th>
              </thead>
              <tbody>
                  <tr *ngFor="let hero of heroes; trackBy: trackHero" >
                      <td>{{hero.name}}</td>
                  </tr>
              </tbody>
          </table>
      `
      })
      export class Heroes {
      
          heroes = HEROES;
      
          trackHero(index, hero) {
              console.log(hero);
              return hero ? hero.id : undefined;
      
          }
      }
      

      【讨论】:

        【解决方案7】:

        你可以使用 trackBy:

        @Component({
        selector:'heroes',
        template: `
        <table>
            <thead>
                <th>Name</th>
            </thead>
            <tbody>
                <tr *ngFor="let hero of heroes; trackBy: trackHero" >
                    <td>{{hero.name}}</td>
                </tr>
            </tbody>
        </table>`})
        
        export class Heroes {
            heroes = HEROES;
        
            trackHero(index, hero) {
                console.log(hero);
            }
        }
        

        【讨论】:

          【解决方案8】:

          最好对订阅中 ngOnInit 中的每个项目进行此类函数调用,然后在转换后使用 *ngFor 显示它们。

          并改变:

          <div *ngFor="let item in items">
          

          <div *ngFor="let item of items">
          

          【讨论】:

          • 你会按照你上面建议的方式提供一些代码吗??
          【解决方案9】:

          模板不是这样做的地方,您希望在组件代码中获取数据。听起来你想使用类似 flatMap 的 observable 的东西,它可以让你为源 observable 中的每个项目返回另一个 observable。这可能是 http api 调用的返回或任何(fiddle):

          var ids = ["a", "d", "c"];
          var lookupValues = { "a": 123, "b": 234, "c": 345, "d": 456 };
          
          // given an id
          function fakeApiCall(id) {
            // given an id, return an observable with one entry: an object consisting
            // of an 'id' property with that id value and a 'lookup' property with the
            // value from lookupValues for that id
            return Rx.Observable.just({ id: id, lookup: lookupValues[id] });
          }
          
          var o1 = Rx.Observable.from(ids); // 'a, d, c
          
          var o2 = o1.flatMap(x => {
            // here we get each value from o1, so we do an api call and return
            // an observable from each that will have the values in that
            // observable combined with all others to be sent to o2
            return fakeApiCall(x);
          });
          
          o2.subscribe(x => {
            document.write(JSON.stringify(x) + "<br/>");
          });
          
          // result:
          // {"id":"a","lookup":123}
          // {"id":"d","lookup":456}
          // {"id":"c","lookup":345}
          

          【讨论】: