【问题标题】:Angular 2: Sort array based on the attribute of the nested objectAngular 2:根据嵌套对象的属性对数组进行排序
【发布时间】:2017-02-22 23:42:11
【问题描述】:

以下是我的 JSON 数据

   {
  "items": [
    {
      "id": 26,
      "email": "pk@gmail.com",
      "firstName": "Poornima ",
      "lastName": "karuppu",
      "role": "Student",
      "studentDetails": {
        "discipline": "History",
        "currentDegree": "Master",
        "currentSemester": 58
      },
      "fullName": "Poornima  karuppu"
    },
    {
      "id": 149,
      "email": "na@mail.uni-paderborn.de",
      "firstName": "raj",
      "lastName": "naga",
      "role": "Student",
      "studentDetails": {
        "discipline": "German Lingustics",
        "currentDegree": "Master",
        "currentSemester": 5
      },
      "fullName": "raj naga"
    },
    {
      "id": 134,
      "email": "testuser@testapp.de",
      "firstName": null,
      "lastName": null,
      "role": "Student",
      "studentDetails": {
        "discipline": "History",
        "currentDegree": "Master",
        "currentSemester": 15
      },
      "fullName": " "
    },
    {
      "id": 20,
      "email": "nn@upb.de",
      "firstName": "null",
      "lastName": "null",
      "role": "Student",
      "studentDetails": {
        "discipline": "History and Arts",
        "currentDegree": "Master",
        "currentSemester": 4
      },
      "fullName": "null null"
    },
    {
      "id": 184,
      "email": "pk@mail.upb.de",
      "firstName": "Rob",
      "lastName": "Pat",
      "role": "Student",
      "studentDetails": {
        "discipline": "Computer Science",
        "currentDegree": "Bachelor",
        "currentSemester": 25
      },
      "fullName": "Rob Pat"
    },
    {
      "id": 151,
      "email": "nn@gmail.com",
      "firstName": null,
      "lastName": null,
      "role": "Student",
      "studentDetails": {
        "discipline": "Art",
        "currentDegree": "Master",
        "currentSemester": 5
      },
      "fullName": " "
    },
    {
      "id": 3,
      "email": "student3@hipapp.de",
      "firstName": "Lamija",
      "lastName": "Halvadzija",
      "role": "Student",
      "studentDetails": {
        "discipline": "Lingustics",
        "currentDegree": "Master",
        "currentSemester": 5
      },
      "fullName": "Lamija Halvadzija"
    },
    {
      "id": 25,
      "email": "neuerstudent@hipapp.de",
      "firstName": "Rolans",
      "lastName": "Mustermann",
      "role": "Student",
      "studentDetails": {
        "discipline": "Linguistics",
        "currentDegree": "Bachelor",
        "currentSemester": 2
      },
      "fullName": "Rolans Mustermann"
    },
    {
      "id": 178,
      "email": "student123@hipapp.de",
      "firstName": null,
      "lastName": null,
      "role": "Student",
      "studentDetails": null,
      "fullName": " "
    },
    {
      "id": 140,
      "email": "neela_upb@hip.com",
      "firstName": "Nilakshi",
      "lastName": "Naphade",
      "role": "Student",
      "studentDetails": null,
      "fullName": "NN"
    },
    {
      "id": 40,
      "email": "pr@gmail.com",
      "firstName": "P",
      "lastName": "K",
      "role": "Student",
      "studentDetails": null,
      "fullName": "PK"
    }

  ],
}

它是我使用 GET API 在 UI 上显示的学生列表。我正在使用 angular 2 管道对这些记录进行排序。以下是 sort.pipe.ts 代码:

import { Injectable, Pipe, PipeTransform } from '@angular/core';

import { User } from '../../../core/user/user.model';

@Pipe({
  name: 'hipUsersSorter'
})
@Injectable()
export class UsersSorter implements PipeTransform {
  transform(users: any, key: string, direction: number): User[] {
    if (key !== '' && users !== null) {
      users.sort(
        (a: any, b: any) => {
          if (a[key] < b[key]) {
            return -1 * direction;
          } else if (a[key] > b[key]) {
            return 1 * direction;
          } else {
            return 0;
          }
        }
      );
    }
    return users;
  }
}

使用这个管道,我可以根据名字、姓氏和电子邮件字段对数据进行排序。但是,我无法根据嵌套属性对记录进行排序,即。纪律,currentDegree 和 currentSemester。以下是我调用此排序管道的 HTML 模板:

<table>
      <thead>
        <tr>
          <th (click)="sort('lastName')">{{ 'last name' | translate }}</th>
          <th (click)="sort('firstName')">{{ 'first name' | translate }}</th>
          <th (click)="sort('email')">{{ 'email' | translate }}</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let user of students | hipUsersFilter: query: selectedOption: selectedRole | hipUsersSorter: key: direction
                  | paginate: { id: 'server', itemsPerPage: 10, currentPage: _page, totalItems: _total }">
          <td>{{ user.lastName }}</td>
          <td>{{ user.firstName }}</td>
          <td>{{ user.email }}</td>
          <td>{{ user.studentDetails.discipline }}</td>
          <td>{{ user.studentDetails.currentDegree }}</td>
          <td>{{ user.studentDetails.currentSemester }}</td>
        </tr>
      </tbody>
    </table>

这是我在组件中的排序功能:

direction = -1;

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

如何根据这些嵌套字段对数据进行排序?有人可以就这个问题提供他们的意见吗? 提前致谢

【问题讨论】:

标签: sorting angular pipe


【解决方案1】:

我会创建一个 method 传递 obj 和嵌套的 'path',如下所示:

import { Injectable, Pipe, PipeTransform } from '@angular/core';

import { User } from '../../../core/user/user.model';

@Pipe({
  name: 'hipUsersSorter'
})
@Injectable()
export class UsersSorter implements PipeTransform {
  transform(users: any, key: string, direction: number): User[] {
    if (key && users !== null && users.length > 0) {
      users.sort(
        (a: any, b: any) => {
          const propertyA: number|string = this.getProperty(a, key);
          const propertyB: number|string = this.getProperty(b, key);

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

  private getProperty (value: { [key: string]: any}, key: string): number|string {
    if (value == null || typeof value !== 'object') {
      return undefined;
    }

    const keys: string[] = key.split('.');
    let result: any = value[keys.shift()];

    for (const key of keys) {
      if (result == null) { // check null or undefined
        return undefined;
      }

      result = result[key];
    }

    return result;
  }
}

在您的模板中:

<th (click)="sort('studentDetails.discipline')">{{ 'discipline' | translate }}</th>
<th (click)="sort('studentDetails.currentDegree')">{{ 'degree' | translate }}</th>
<th (click)="sort('studentDetails.currentSemester')">{{ 'semester' | translate }}</th>

简单演示:DEMO

【讨论】:

  • 它适用于 studentDetails 不为空的记录。但是我完整的 JSON 数据有许多记录,其中 studentDetails = null 并且在这种情况下它不起作用。 :(
  • 你没有在你的问题中提到它:) 你对那些有空值的人有什么期望?随意 fork 演示以包含您的 null objects
  • 抱歉没有提及。我已在上述问题中添加了所有 JSON 数据。我没有更改/分叉 plunker。
  • 好吧,上面的 method 在处理 null 值时工作正常。你的问题可能出在模板中。使用 safe-navigation operator 这样:&lt;td&gt;{{ user.studentDetails?.discipline }}&lt;/td&gt;
  • 嘿,它起作用了。我不知何故忘记在 getProperty 方法中添加结果语句。所以结果是不确定的。非常感谢:)
猜你喜欢
  • 2019-07-11
  • 1970-01-01
  • 2018-05-24
  • 1970-01-01
  • 2023-01-06
  • 2021-03-04
  • 2018-07-02
  • 2015-06-17
相关资源
最近更新 更多