typescript 如何在Angular中使用自定义管道按属性值对对象数组进行排序?

pgky5nke  于 2023-05-19  发布在  TypeScript
关注(0)|答案(3)|浏览(172)

我需要在Angular中编写一个自定义管道,它接受一个对象数组和一个名为order的变量,该变量的值为ascendingdescending作为参数,然后按属性值对对象数组进行排序。
数据看起来像这样:

[
    {
        "location_type": "KAUPPA",
        "postalcode": "100",
        "availability": "LIIKETILAN AUKIOLO",
        "location": "SUOMALAINEN KIRJAKAUPPA / SISÄKÄYTÄVÄ",
        "municipality": "TURKU",
        "target_address": "ALEKSANTERINKATU 23",
        "availability_details": "",
        "coordinates_lon": "24.941095",
        "coordinates_lat": "60.168718"
    },
    {
        "location_type": "PANKIN KONTTORI",
        "postalcode": "100",
        "availability": "ITSEPALVELUALUEEN AUKIOLO",
        "location": "NORDEA SENAATINTORI",
        "municipality": "VANTAA",
        "target_address": "ALEKSANTERINKATU 30",
        "availability_details": "ma-su klo 06-22",
        "coordinates_lon": "24.950720",
        "coordinates_lat": "60.168930"
    },
    {
        "location_type": "TAVARATALO",
        "postalcode": "100",
        "availability": "LIIKETILAN AUKIOLO",
        "location": "STOCKMANN / 8. KERROS",
        "municipality": "HELSINKI",
        "target_address": "ALEKSANTERINKATU 52",
        "availability_details": "",
        "coordinates_lon": "24.941870",
        "coordinates_lat": "60.168430"
    }
]

数组中的对象需要按照municipality的值进行排序。

qgelzfjb

qgelzfjb1#

正如在评论中多次提到的,以及Pardeep的上述答案,使用Pipe对数据进行排序不是一个很好的主意。
如果您想对字段进行排序,只需在模板上实现它,然后仅在事件上触发排序函数。这将大大保存您的性能。
在这里,给予这个一个尝试:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  lastSortedByField;
  ascendingOrder = true;
  data = [
    {
      "location_type": "KAUPPA",
      "postalcode": "100",
      "availability": "LIIKETILAN AUKIOLO",
      "location": "SUOMALAINEN KIRJAKAUPPA / SISÄKÄYTÄVÄ",
      "municipality": "TURKU",
      "target_address": "ALEKSANTERINKATU 23",
      "availability_details": "",
      "coordinates_lon": "24.941095",
      "coordinates_lat": "60.168718"
    },
    {
      "location_type": "PANKIN KONTTORI",
      "postalcode": "100",
      "availability": "ITSEPALVELUALUEEN AUKIOLO",
      "location": "NORDEA SENAATINTORI",
      "municipality": "VANTAA",
      "target_address": "ALEKSANTERINKATU 30",
      "availability_details": "ma-su klo 06-22",
      "coordinates_lon": "24.950720",
      "coordinates_lat": "60.168930"
    },
    {
      "location_type": "TAVARATALO",
      "postalcode": "100",
      "availability": "LIIKETILAN AUKIOLO",
      "location": "STOCKMANN / 8. KERROS",
      "municipality": "HELSINKI",
      "target_address": "ALEKSANTERINKATU 52",
      "availability_details": "",
      "coordinates_lon": "24.941870",
      "coordinates_lat": "60.168430"
    }
  ];

  sortByField(field) {
    if(this.lastSortedByField === field) {
      this.ascendingOrder = !this.ascendingOrder;
    }
    else {
      this.lastSortedByField = field;
      this.ascendingOrder = true;
    }

    if(this.ascendingOrder) {
      this.data = this.data.sort((a, b) => {
        if (a[field] < b[field])
          return -1;
        if (a[field] > b[field])
          return 1;
        return 0;
      });
    } else {
      this.data = this.data.sort((a, b) => {
        if (a[field] < b[field])
          return 1;
        if (a[field] > b[field])
          return -1;
        return 0;
      });
    }

  }

}

在模板中:

<table border="1">
  <thead>
    <tr>
      <td (click)="sortByField('location_type')">location_type</td>
      <td (click)="sortByField('postalcode')">postalcode</td>
      <td (click)="sortByField('availability')">availability</td>
      <td (click)="sortByField('location')">location</td>
      <td (click)="sortByField('municipality')">municipality</td>
      <td (click)="sortByField('target_address')">target_address</td>
      <td (click)="sortByField('availability_details')">availability_details</td>
      <td (click)="sortByField('coordinates_lon')">coordinates_lon</td>
      <td (click)="sortByField('coordinates_lat')">coordinates_lat</td>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let datum of data">
      <td>{{ datum.location_type }}</td>
      <td>{{ datum.postalcode }}</td>
      <td>{{ datum.availability }}</td>
      <td>{{ datum.location }}</td>
      <td>{{ datum.municipality }}</td>
      <td>{{ datum.target_address }}</td>
      <td>{{ datum.availability_details }}</td>
      <td>{{ datum.coordinates_lon }}</td>
      <td>{{ datum.coordinates_lat }}</td>
    </tr>
  </tbody>
</table>

这里有一个Working Sample StackBlitz给你的参考。

nle07wnf

nle07wnf2#

官方文档-过滤,尤其是排序是昂贵的操作。
Angular团队和许多经验丰富的Angular开发人员强烈建议将过滤和排序逻辑移动到组件本身。
一般来说,这种情况下不需要使用自定义管道,而是可以直接将数据排序到组件类中。但是如果你想使用pipe,请参考下面的内容-

@Pipe({name: 'sorted'})
export class SortedPipe implements PipeTransform {
  transform(value: any){
    const data =  value.sort((a,b) => a.municipality.localeCompare(b.municipality));
    return data;
  } 
}

Working example

von4xj4u

von4xj4u3#

使用ramda的类型安全解决方案:

import {Pipe, PipeTransform} from '@angular/core';
import {prop, sortBy} from 'ramda';

@Pipe({name: 'sortBy', standalone: true})
export class SortByPipe implements PipeTransform {
  public transform<T>(value: Array<T>, sortByKey: keyof T): Array<T> {
    return sortBy(prop(sortByKey))(value);
  }
}

相关问题