从嵌套 json 排序的 Angular 4 数据表
Posted
技术标签:
【中文标题】从嵌套 json 排序的 Angular 4 数据表【英文标题】:Angular 4 data-table sorting from nested json 【发布时间】:2019-01-20 05:15:20 【问题描述】:需要有关嵌套数据的 Angular 数据表的帮助。
我想对表格中的数据进行排序。
我正在使用来自 - https://www.npmjs.com/package/angular2-datatable 的数据表
数据表适用于单一数组类型的数据。 (用于许多角度应用)
问题:我有嵌套的json(实际上,我有复杂的json,这里很简单)
感谢您对此进行调查。
感谢任何建议或帮助。
JSON
records = [
[
"name": "Subject Name",
"type": "text",
"id": "subjectName",
"value": "DavidJ",
"firstName": "David",
"lastName": "John"
,
"name": "QC Name",
"type": "hidden",
"id": "qcName",
"value": "JosephT",
"firstName": "Joseph",
"lastName": "Tom"
],
[
"name": "Subject Name",
"type": "text",
"id": "subjectName",
"value": "TigerC",
"firstName": "Tiger",
"lastName": "Chan"
,
"name": "QC Name",
"type": "hidden",
"id": "qcName",
"value": "ThomasR",
"firstName": "Thomas",
"lastName": "Richard"
]
]
HTML
<table class="table table-responsive table-hover" [mfData]="this.records | dataFilter : filterQuery" #mf="mfDataTable" [mfRowsOnPage]="rowsOnPage" [(mfSortBy)]="sortBy" [(mfSortOrder)]="sortOrder">
<thead>
<tr>
<th>#</th>
<th>
<mfDefaultSorter by="subjectName">subject Name</mfDefaultSorter>
</th>
<th>
<mfDefaultSorter by="qcPerson">QC Person</mfDefaultSorter>
</th>
</tr>
</thead>
<tbody *ngIf="!isLoading">
<tr class="border" *ngFor="let sample of mf.data; let i='index'">
<td>i + 1</td>
<ng-container *ngFor="let item of sample">
<td *ngIf="item.id ==='subjectName'">
item.firstName item.lastName
</td>
<td *ngIf="item.id ==='qcPerson'">
item.firstName item.lastName
</td>
</ng-container>
</tr>
</tbody>
</table>
打字稿文件
import Component, OnInit from '@angular/core';
import OrderBy from '../all_services/OrderByPipe';
@Component(
selector: 'app-userdashboard',
templateUrl: './userdashboard.component.html',
styleUrls: ['../header-footer/css/external.style.css']
)
export class UserdashboardComponent implements OnInit
constructor()
ngOnInit()
/** Sorting functions */
public data;
public filterQuery = "";
public rowsOnPage = 10;
public sortBy = "subjectName";
public sortOrder = "asc";
public toInt(num: string)
return +num;
Datafilterpipe.ts
import * as _ from "lodash";
import Pipe, PipeTransform from "@angular/core";
@Pipe(
name: "dataFilter"
)
export class DataFilterPipe implements PipeTransform
transform(array: any[], query: string): any
if (query)
return _.filter(array, row=>row.name.indexOf(query) > -1);
return array;
【问题讨论】:
您的问题不清楚 - 您想做什么需要帮助? @GabrielDoty,如果我不清楚,请道歉。我想对表格中的数据进行排序。 为什么要在数组中使用数组,不能简单地将所有对象放在一个数组中,这样对象数组的排序会容易得多 在填充表格之前展平 JSON 怎么样? angular-yfpnk4.stackblitz.io @Prasanna Sasne,恐怕我做不到。我在许多其他组件中使用相同的 json。我有复杂的嵌套 json,在这里我显示非常简单的 json 【参考方案1】:我也遇到过同样的问题。一旦表格在 DOM 中呈现,我就使用了w3school 表格排序逻辑。
它与 angular2-datatable 一起工作非常顺利,因为我在我的项目中使用相同的数据表。它的用法很简单,如果您遇到任何问题,请告诉我。
提前致谢。
下面将是实现 TS 文件中的函数。
columnSorter(n)
let table, rows, switching, i, x, y, shouldSwitch, dir, switchCount = 0;
switching = true;
this.clickSort = !this.clickSort
dir = "asc";
table = document.querySelector('.smallTable');
while (switching)
switching = false;
rows = table.rows;
for (i = 0; i < (rows.length - 1); i++)
shouldSwitch = false;
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
if (dir == 'asc')
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase())
shouldSwitch = true;
break;
else if (dir == 'desc')
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase())
shouldSwitch = true;
break;
if (shouldSwitch)
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
switchCount++;
else
if (switchCount == 0 && dir == 'asc')
dir = 'desc';
switching = true;
在您的 HTML 表格中,只需在下面添加,其中 0 是列号。
(click)="columnSorter(0)
【讨论】:
确实达不到我的要求。谢谢你的主意。我真的很感激。 如果你不介意能告诉我你的要求是什么吗? 我想通过单击向上和向下箭头对表头进行排序。我有 4 张桌子,我不希望用户多按一个按钮来排序。 您不需要单独的按钮,在点击列时调用该函数。检查我编辑的答案 @ManjunathSiddappa 如果我的回答能解决您的问题,那么请将其标记为回答【参考方案2】:使用这个库,您必须使用这些输入变量对表格进行一次排序:
mfSortBy: any - sort by parameter
mfSortOrder: string - sort order parameter, "asc" or "desc"
你也可以给你添加这个标签,让用户通过点击对其进行排序:
<mfDefaultSorter by="name">Name</mfDefaultSorter>
要为表格创建自定义排序,您只需对您的 json 进行排序。 在您的情况下,您应该使用分配给 mf.data 的内容进行操作。
您可以创建自定义指令,在其中为表格创建排序器,然后通过单击对数据进行排序。
例如
import
Directive, ElementRef, AfterViewChecked,
Input, Output, Renderer, EventEmitter
from '@angular/core';
@Directive(
selector: '[sorter], [defaultSorter]'
)
export class TableSorterDerective implements AfterViewChecked
@Input()
sorter: order:string, property:string;
@Output()
sorted = new EventEmitter();
constructor(private el: ElementRef, private renderer: Renderer)
ngAfterViewChecked()
let element: HTMLElement = this.el.nativeElement;
if(this.sorter)
this.addSorter(element);
addSorter(column: HTMLElement)
if(!column.classList.contains("custom_sorter"))
column.addEventListener('click', () => this.sendSort(column), false)
column.classList.add("custom_sorter");
sendSort(element:HTMLElement)
let columns: HTMLElement[] =
Array.prototype.slice.call(element.parentElement.getElementsByTagName('th'), 0);
columns.forEach(element =>
if(!element.classList.contains(this.sorter.property))
let icon = element.getElementsByTagName('span')[0];
if(icon) icon.remove();
);
let icon:HTMLElement = element.getElementsByTagName('span')[0];
if(!icon) icon = this.renderer.createElement(element, 'span');
icon.classList.remove("glyphicon-triangle-bottom")
icon.classList.remove("glyphicon-triangle-top")
icon.classList.remove("glyphicon")
if(this.sorter.order == "asc")
this.sorter = order:"desc", property:this.sorter.property
icon.classList.add("glyphicon")
icon.classList.add("glyphicon-triangle-top")
else if(this.sorter.order == "desc")
this.sorter = order:"asc", property:this.sorter.property
icon.classList.add("glyphicon")
icon.classList.add("glyphicon-triangle-bottom")
this.sorted.emit(this.sorter)
然后您只需要在发出时对数据进行排序:
<th *ngFor="let col of columns" [sorter]="col.sorting ? order:'desc', property:col.property : undefined" (sorted)="transformationsService.sort(filteredData, $event)"</th>
要对数据进行排序,只需使用排序功能,例如:
data.sort((a, b) =>
return 0 - (a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1)
如果您需要有关排序功能的帮助,请参阅this question。
【讨论】:
谢谢你让我检查一下。我不是在寻找自定义排序,但我也会尝试。 你应该知道这个表只允许你按第一层属性排序,所以如果你想使用非自定义排序器,你需要将输入数据简化为对象,如 subjectName:string; qcPerson:string 然后你可以使用要对数据进行排序,您始终可以使用 Lodash 非常强大的 _.sortBy
:
import * as _ from 'lodash';
const nestedData = [
a: b: 2 ,
a: b: 1 ,
a: b: 3
];
// Outputs [ a: b: 1 , a: b: 2 , a: b: 3 ]
_.sortBy(nestedData, item => _.get(item, ['a', 'b']));
它甚至支持按多个字段排序:
import * as _ from 'lodash';
const nestedData = [
a: b: 2 , c: 'a' ,
a: b: 1 , c: 'b' ,
a: b: 1 , c: 'd'
];
// Output:
// [ a: b: 1 , c: 'b' ,
// a: b: 1 , c: 'd' ,
// a: b: 2 , c: 'a' ]
_.sortBy(nestedData, [item => _.get(item, ['a', 'b']), item => _.get(item, 'c')]);
至于将其添加到您当前的表格中 - 您可以通过多种方式实现这一目标。在将数据传递给表格之前对数据进行预排序可能会更容易。如果用户单击列标题 - 只需通过适当的 _.sortBy
运行数据并将其转储回表中?
【讨论】:
如果可以的话请给我fiddle或plunker json好吗【参考方案4】:您可以实现自定义管道,而不是使用 dataTable,这将对数据进行排序,而无需更改原始对象。单击列时您希望如何对数据进行排序。这是简单的代码,希望对你有用。
import Pipe, PipeTransform from "@angular/core";
@Pipe(
name: "orderby",
pure: false
)
export class OrderByPipe implements PipeTransform
transform(array: Array<any>, args?: any)
let newDataArray:any = [];
if (array.length > 0 && args.value != undefined)
for (let item of array)
for (let subItem of item)
newDataArray.push(subItem);
newDataArray.sort((a: any, b: any) =>
if ((a.firstName).toLowerCase() < (b.firstName).toLowerCase())
return -1 * args.direction;
else if ((a.firstName).toLowerCase() > (b.firstName).toLowerCase())
return 1 * args.direction;
else
return 0;
);
array = Array.from(newDataArray);
return array;
要从您的组件使用代码调用此管道,请定义这些变量
isDesc: boolean = false;
direction: number = 1;
filterData = [];
和
orderByMe(toBeSorted: string)
this.isDesc = !this.isDesc;
this.direction = this.isDesc ? 1 : -1;
this.filterData = Array.from(new OrderByPipe().transform( this.records,
value: toBeSorted, direction: this.direction ));
ngOnInit()
this.orderByMe('subjectName');
在 Html 模板中可以使用
<table>
<thead>
<tr>
<th>#</th>
<th (click)="orderByMe('subjectName')">subjectName</th>
<th (click)="orderByMe('qcName')">qcPerson</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let record of filterData; let currentIndex = index;">
<td> currentIndex + 1</td>
<td> record.firstName </td>
<td> record.lastName </td>
</tr>
</tbody>
</table>
【讨论】:
以上是关于从嵌套 json 排序的 Angular 4 数据表的主要内容,如果未能解决你的问题,请参考以下文章
以编程方式从 Angular 2 中的 json 创建嵌套组件
如何在 Angular 中为嵌套的 JSON 对象使用搜索过滤器?