【问题标题】:Angular 2 pipe: Using a same pipe for two different arrays in single ngForAngular 2 管道:在单个 ngFor 中为两个不同的数组使用相同的管道
【发布时间】:2023-03-12 16:10:01
【问题描述】:

以下是JSON数据:

{
  "tagFrequency": [
    {
      "value": "At",
      "count": 1,
      "tagId": 249
    },
    {
      "value": "ipsum",
      "count": 1,
      "tagId": 251
    },
    {
      "value": "molestie",
      "count": 1,
      "tagId": 199
    }
  ]
}

我在 UI 上将这些数据填充到一个表中,该表的列名分别为单词、上述 JSON 对象属性值的频率和计数。使用 tagId 属性通过 GET API 调用提取第三列标记名。以下是我的 HTML 代码:

<table>
  <thead>
    <tr>
      <th (click)="sort('value')">{{ 'word' | translate }}</th>
      <th (click)="sort('tagId')">{{ 'tag-name' | translate }}</th>
      <th (click)="sort('count')">{{ 'frequency' | translate }}</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let frequency of (frequencies | TagFrequencySorter: key: direction); let i = index;">
      <td>{{ frequency.value }}</td>
      <td>{{ processedTagNames[i] }}</td>
      <td>{{ frequency.count }}</td>
    </tr>
  </tbody>
</table>

我想对这些列的值和计数进行排序,这与“TagFrequencySorter”管道一起使用。但我也想在同一个 for 循环中使用同一个管道对 tagNames 数组数据进行排序。我可以在管道中进行必要的更改,但我只想以某种方式将这两个数组传递给这个管道。

下面是我在组件里写的一个排序函数:

sort(value: string) {
    this.direction = this.direction * (-1);
    if(value === "tagId") {
      this.key = "";
    }
    else {
      this.key = value;
    }
  }

这里是管道实现:

export class TagFrequencySorter implements PipeTransform {
  transform(tagFrequencies: any, key: string, direction: number): any[] {
    if (key !== '' && tagFrequencies !== null) {
      console.log(key)
      tagFrequencies.sort(
        (a: any, b: any) => {
          let propertyA: number|string = this.getProperty(a, key);
          let propertyB: number|string = this.getProperty(b, key);

          if (propertyA < propertyB) {
            return -1 * direction;
          } else if (propertyA > propertyB) {
            return 1 * direction;
          } else {
            return 0;
          }
        }
      );
    }
    return tagFrequencies;
  }

  private getProperty(value: { [key: string]: any}, key: string): number|string {
    if (value === null || typeof value !== 'object') {
      return undefined;
    }
    let keys: string[] = key.split('.');
    let result: any = value[keys.shift()];
    for (let newkey of keys) {
      if (result === null) {
        return undefined;
      }
      result = result[newkey];
    }
    return result;
  }
}

有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: sorting angular pipe


    【解决方案1】:

    实现此目的的一种方法是通过将自定义管道作为提供程序传递给您的组件来预处理您的 tagNames 数组

    constructor(private _tagFrequencySorterPipe: TagFrequencySorter){ }
    
    get processedTagNames(){
        return this._tagFrequencySorterPipe(this.tagNames, this.key, this.direction);    
    }
    

    您的 HTML 将如下所示:

    <tr *ngFor="let frequency of (frequencies | TagFrequencySorter: key: direction); let i = index;">
        <td>{{ frequency.value }}</td>
        <td>{{ processedTagNames[i] }}</td>
        <td>{{ frequency.count }}</td>
    </tr>
    

    有关 Angular2 中管道依赖注入的更多信息,请参阅question


    另一种选择是merge the two arrays 一起使用单独的管道,然后修改现有的排序管道以处理合并的数组:

    <tr *ngFor="let item of (frequencies | merge: tagNames |TagFrequencySorter: key: direction); let i = index;">
        <td>{{ item.frequency.value }}</td>
        <td>{{ item.tagName }}</td>
        <td>{{ item.frequency.count }}</td>
    </tr>
    

    【讨论】:

    • 感谢您的回复。我使用了预处理 tagNmaes 的第一种方法。但是我怎样才能在标题名称上使用 onClick() 调用这个 processesName 方法。我想使用 onClick 对各自的标题名称进行排序,就像我对其他两个标题所做的那样。请查看我上面更新的 HTML 代码
    • 在这种情况下,听起来合并选项对你来说是最简单的选择
    猜你喜欢
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 2017-01-12
    • 2020-06-21
    • 2017-03-13
    • 2020-10-28
    • 2017-09-09
    • 1970-01-01
    相关资源
    最近更新 更多