Angular 4 data-table sorting from nested json Angular 4 data-table sorting from nested json json json

Angular 4 data-table sorting from nested json


I had face the same issue. I had used w3school table sort logic once the table is rendered in DOM.

It works really smooth with angular2-datatable as I am using the same datatable in my project. Its usage is very straight, stillif you face any issue please let me know.

Thanks in advance.

Below will be implementationFunction in your TS file.

  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;        }      }    }  }

In you HTML table on th just add below, where 0 is column no.

(click)="columnSorter(0)


Using this library you have to use these input variables to sort table once:

mfSortBy: any - sort by parametermfSortOrder: string - sort order parameter, "asc" or "desc"

Also you can add this tag to you th to allow user to sort it by click:

<mfDefaultSorter by="name">Name</mfDefaultSorter>

To create custom sort for the table you just need to sort yours json.In your case you should operate with what you assign to mf.data.

You can create custom derective where you will create sorter for a table and then sort data by click.

e.g.

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)  }}

and then you just need to sort data on emit:

    <th *ngFor="let col of columns" [sorter]="col.sorting ? {order:'desc', property:col.property} : undefined" (sorted)="transformationsService.sort(filteredData, $event)"</th>

To sort data just use sort function e.g. :

data.sort((a, b) => {        return 0 - (a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1)      }

See this question if you need help with sort function.


To sort the data you could always use Lodash's very powerful _.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']));

It even supports sorting by multiple fields:

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')]);

As far as adding this to your current table -- there are a lot of ways you can achieve that. It might be easier to pre-sort your data before you pass it the table. If the user clicks a column header -- simply run the data through the appropriate _.sortBy and dump it back into the table?