Tableau de données angulaires 4-tri à partir de json emboîtées

besoin d'aide sur les données angulaires-table avec des données emboîtées.

je veux trier les données dans le tableau.

je suis en utilisant la table de données à partir d' - https://www.npmjs.com/package/angular2-datatable

table de données fonctionne bien pour les données de type de tableau simple. (utilisé pour de nombreuses applications angulaires)

ISSUE: j'ai imbriqué json (en réalité, j'ai complexes json, faire ici simple)

Merci d'avoir regardé dans ce.

toute suggestion ou aide est appréciée.

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>

fichier dactylographié

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;
    }
}
13
demandé sur Manjunath Siddappa 2018-08-13 15:56:01

4 réponses

j'avais fait face au même problème. J'avais utilisé w3school logique de tri de table une fois que la table est rendue dans DOM.

cela fonctionne très bien avec angular2-datatable car j'utilise le même datatable dans mon projet. Son usage est très droit, stillif vous faire face à tout problème s'il vous plaît laissez-moi savoir.

Merci à l'avance.

ci-Dessous sera mise en œuvre Fonction dans votre fichier 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;
        }
      }
    }
  }

dans votre tableau HTML sur th juste Ajouter ci-dessous, où 0 est la colonne no.

(click)="columnSorter(0)
6
répondu Krishna 2018-08-20 11:32:09

en utilisant cette bibliothèque vous devez utiliser ces variables d'entrée pour trier la table une fois:

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

vous pouvez aussi ajouter cette balise à votre th pour permettre à l'utilisateur de la trier en cliquant sur:

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

pour créer le tri personnalisé pour la table vous avez juste besoin de trier votre json. Dans votre cas, vous devez opérer avec ce que vous assignez à mf.données.

vous pouvez créer custom derective où vous créerez sorter pour une table et ensuite trier les données par cliquer.

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

et ensuite, vous avez juste besoin de trier les données à émettre:

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

pour trier les données, utilisez simplement la fonction de tri, par exemple :

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

Voir cette question si vous avez besoin d'aide avec la fonction de tri.

5
répondu Vlad Kostyukevich 2018-08-14 08:19:36

pour trier les données, vous pouvez toujours utiliser le très puissant _.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']));

il supporte même le tri par champs multiples:

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

en ce qui concerne l'ajout de ceci à votre tableau actuel -- il y a beaucoup de façons d'y arriver. Il pourrait être plus facile de pré-trier vos données avant de passer à la table. Si l'utilisateur clique sur un en-tête de colonne -- lancez simplement les données à travers le_.sortBy et le jeter à nouveau dans la table?

5
répondu Pearman 2018-08-20 16:50:40

au lieu d'utiliser dataTable vous pouvez implémenter custom pipe, qui va trier les données, sans changer l'objet original. Certains comment vous voulez trier les données lorsque vous avez cliqué sur les colonnes. Voici un code simple, espérons que cela fonctionne pour vous.

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

pour appeler cette pipe à partir de votre code d'utilisation de composant comme ci-dessous, définissez ces variables

isDesc: boolean = false;
direction: number = 1;
filterData = [];

et

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

dans le modèle Html vous pouvez utiliser

<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>
4
répondu Prasanna Sasne 2018-08-22 10:17:40