Ordenar tablas en Angular

Oluwafisayo Oluwatayo 20 marzo 2023
  1. Ordenar tabla con material angular
  2. Ordenar tabla con Bootstrap
  3. Ordenar tabla usando el ng-model
  4. Conclusión
Ordenar tablas en Angular

Las páginas web son una excelente manera de hacer presentaciones; a la hora de preparar datos estadísticos, hacer una lista de precios de artículos, o clasificar artículos, se requiere mayormente que hagamos una tabla que nos permita ordenar estas listas.

Podemos ordenar la tabla en orden ascendente, descendente, etc. Veamos ahora los mejores métodos que podemos aplicar para crear tablas con funcionalidad de ordenación dentro del marco Angular.

Ordenar tabla con material angular

Ya no es noticia que la dependencia de material de Angular sea la biblioteca de referencia para todo tipo de componente de Angular; instalaremos la biblioteca Angular Material para este método.

Después de que se haya creado la carpeta del proyecto, vaya a la carpeta del proyecto en su terminal e instale la dependencia de Angular Material con: ng add @angular/material; una vez hecho esto, lo siguiente es crear la estructura de la página con códigos preparados para el Material angular para la tabla de clasificación.

Dentro del archivo app.component.html, insertamos estos códigos.

Fragmento de código app.component.html:

<table mat-table [dataSource]="dataSource" matSort (matSortChange)="announceSortChange($event)"
  class="mat-elevation-z8">
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by number">
      No.
    </th>
    <td mat-cell *matCellDef="let element"> {{element.position}} </td>
  </ng-container>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by name">
      Name
    </th>
    <td mat-cell *matCellDef="let element"> {{element.name}} </td>
  </ng-container>
  <ng-container matColumnDef="weight">
    <th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by weight">
      Weight
    </th>
    <td mat-cell *matCellDef="let element"> {{element.weight}} </td>
  </ng-container>
  <ng-container matColumnDef="symbol">
    <th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by symbol">
      Symbol
    </th>
    <td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
  </ng-container>
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

Estamos configurando la estructura de la tabla dentro de este archivo como los encabezados, filas y columnas.

A continuación, vamos al archivo app.component.ts para configurar los códigos que controlarán la tabla; escribiremos estos códigos:

Fragmento de código app.component.ts:

import { LiveAnnouncer } from '@angular/cdk/a11y';
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { MatSort, Sort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
  { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
  { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
  { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
  { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
  { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
  { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
  { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
  { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
  { position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
  { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
];
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  title = 'sortone';
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = new MatTableDataSource(ELEMENT_DATA);
  constructor(private _liveAnnouncer: LiveAnnouncer) { }
  @ViewChild(MatSort) sort: MatSort;
  ngAfterViewInit() {
    this.dataSource.sort = this.sort;
  }
  announceSortChange(sortState: Sort) {
    if (sortState.direction) {
      this._liveAnnouncer.announce(`Sorted ${sortState.direction}ending`);
    } else {
      this._liveAnnouncer.announce('Sorting cleared');
    }
  }
}

Primero, importamos los módulos requeridos de la biblioteca Angular Material; luego, declaramos el tipo de entrada que habrá en cada encabezado de tabla; para name, declaramos tipo string, y para weight y position, declaramos tipo number.

Luego declaramos los datos que queremos en la tabla en forma de matriz; a continuación, pasamos a crear la función sort usando this.dataSource.sort.

El archivo app.module.ts es el módulo que maneja los módulos y las dependencias que usamos para nuestra aplicación, por lo que debemos importar las dependencias aquí. El archivo debe verse como se muestra a continuación.

Fragmento de código app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatTableModule } from '@angular/material/table';
import { FormsModule } from '@angular/forms';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { MatSortModule } from '@angular/material/sort';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatTableModule,
    FormsModule,
    DragDropModule,
    MatSortModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

¿Dónde está la belleza y la ubicación de una página sin CSS? Simplemente agregue este pequeño fragmento de código en el archivo app.component.css como se muestra a continuación.

Fragmento de código app.component.css:

table {
    width: 100%;
  }

  th.mat-sort-header-sorted {
    color: black;
  }

Producción:

Ordenar tabla con material angular

Ordenar tabla con Bootstrap

Bootstrap facilita la vida de un programador; donde deberíamos escribir una novela de códigos, Bootstrap nos ayuda a escribir códigos más concisos con una mejor funcionalidad.

Al igual que el material angular, igualmente instalaremos la biblioteca Bootstrap dentro de la carpeta del proyecto con ng add @ng-bootstrap/ng-bootstrap. Luego de una instalación exitosa, navegamos al archivo app.component.html para escribir estos códigos.

Fragmento de código app.component.html:

<h2>Sort Table with Bootstrap</h2>
<table class="table table-striped">
  <thead>
  <tr>
    <th scope="col">#</th>
    <th scope="col" sortable="name" (sort)="onSort($event)">Country</th>
    <th scope="col" sortable="area" (sort)="onSort($event)">Area</th>
    <th scope="col" sortable="population" (sort)="onSort($event)">Population</th>
  </tr>
  </thead>
  <tbody>
  <tr *ngFor="let country of countries">
    <th scope="row">{{ country.id }}</th>
    <td>
      <img [src]="'https://upload.wikimedia.org/wikipedia/commons/' + country.flag" class="me-2" style="width: 20px">
      {{ country.name }}
    </td>
    <td>{{ country.area | number }}</td>
    <td>{{ country.population | number }}</td>
  </tr>
  </tbody>
</table>

Aquí creamos la estructura de la tabla y los encabezados; ahora, debemos dirigirnos al archivo app.component.ts para escribir los códigos para que la tabla funcione.

El archivo se verá como el siguiente.

Fragmento de código app.component.ts:

import { Component, Directive, EventEmitter, Input, Output, QueryList, ViewChildren } from '@angular/core';

interface Country {
  id: number;
  name: string;
  flag: string;
  area: number;
  population: number;
}
const COUNTRIES: Country[] = [
  {
    id: 1,
    name: 'Russia',
    flag: 'f/f3/Flag_of_Russia.svg',
    area: 17075200,
    population: 146989754
  },
  {
    id: 2,
    name: 'Canada',
    flag: 'c/cf/Flag_of_Canada.svg',
    area: 9976140,
    population: 36624199
  },
  {
    id: 3,
    name: 'United States',
    flag: 'a/a4/Flag_of_the_United_States.svg',
    area: 9629091,
    population: 324459463
  },
  {
    id: 4,
    name: 'China',
    flag: 'f/fa/Flag_of_the_People%27s_Republic_of_China.svg',
    area: 9596960,
    population: 1409517397
  }
];

export type SortColumn = keyof Country | '';
export type SortDirection = 'asc' | 'desc' | '';
const rotate: {[key: string]: SortDirection} = { 'asc': 'desc', 'desc': '', '': 'asc' };
const compare = (v1: string | number, v2: string | number) => v1 < v2 ? -1 : v1 > v2 ? 1 : 0;
export interface SortEvent {
  column: SortColumn;
  direction: SortDirection;
}
@Directive({
  selector: 'th[sortable]',
  host: {
    '[class.asc]': 'direction === "asc"',
    '[class.desc]': 'direction === "desc"',
    '(click)': 'rotate()'
  }
})
export class NgbdSortableHeader {
  @Input() sortable: SortColumn = '';
  @Input() direction: SortDirection = '';
  @Output() sort = new EventEmitter<SortEvent>();
  rotate() {
    this.direction = rotate[this.direction];
    this.sort.emit({column: this.sortable, direction: this.direction});
  }
}
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'sortfive';
  countries = COUNTRIES;
  @ViewChildren(NgbdSortableHeader) headers!: QueryList<NgbdSortableHeader>;
  onSort({column, direction}: SortEvent) {
    this.headers.forEach(header => {
      if (header.sortable !== column) {
        header.direction = '';
      }
    });
    if (direction === '' || column === '') {
      this.countries = COUNTRIES;
    } else {
      this.countries = [...COUNTRIES].sort((a, b) => {
        const res = compare(a[column], b[column]);
        return direction === 'asc' ? res : -res;
      });
    }
  }
}

Aquí primero declaramos el tipo de datos que se ingresarán dentro de cada tabla, y dado que ordenaremos los elementos de los encabezados, debemos declarar el NgbdSortableHeader en una clase de export.

Luego nos dirigimos al archivo app.module.ts para importar los módulos necesarios que aplicamos desde ng-bootstrap.

Fragmento de código app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent, NgbdSortableHeader } from './app.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { CommonModule } from '@angular/common';

@NgModule({
  declarations: [
    AppComponent,NgbdSortableHeader
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    NgbModule,
    CommonModule
  ],
  exports: [AppComponent],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Producción:

Ordenar tabla con Bootstrap

Ordenar tabla usando el ng-model

Este ejemplo es el código más eficiente de todos porque, a diferencia de los dos primeros que utilizan todos los componentes de la carpeta app, este ejemplo utiliza solo el archivo index.html porque el ng-model puede enlazar el valor de los controles HTML a los datos de la aplicación. Además, no tiene que instalar ninguna dependencia para que este método funcione.

Una vez creada la carpeta del proyecto, nos dirigimos al archivo index.html para escribir estos códigos.

index.html:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Sortfour</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
  <body>
    <div class="container">
        <div ng-app="myApp" ng-controller="namesCtrl" ng-init="IsReverse=false">
        Search: <input type="text" ng-model="test"><br>
        <table class="table table-hover table-bordered table-striped">
          <tr>
              <th ng-click="sort('Name')">Name
              <th ng-click="sort('Age')">Age
              <th ng-click="sort('Email')">Email
              <th>Actions</th>
          </tr>
          <tr ng-repeat="x in names | filter:test | orderBy:sortParam:IsReverse">
              <td>{{x.Name}}
              <td>{{x.Age}}
              <td>{{x.Email}}
              <td>
                <div class="btn-group">
                    <a class="btn btn-primary" href="#">EDIT</a>
                    <a class="btn btn-primary" href="#">DELETE</a>
                </div>
              </td>
          </tr>
          </table>

    </div>

    <script>
    angular.module('myApp', []).controller('namesCtrl', function($scope) {
        $scope.names = [
            {Name:'Manav',Age:'22',Email:'pandya.manav@gmail.com'},
            {Name:'Rahul',Age:'25',Email:'pnd.rahul@gmail.com'},
            {Name:'Rohan',Age:'28',Email:'pnd.rohan@gmail.com'},
            {Name:'Jinish',Age:'18',Email:'jinish@gmail.com'}
        ];
        $scope.sort = function(sortId) {
            $scope.sortParam =  sortId;
            if($scope.IsReverse)
            {
                $scope.IsReverse = false;
            }
            else
            {
                $scope.IsReverse = true;
            }
        };
    });
    </script>
    </body>
</body>
</html>

Primero, creamos las tablas. Luego agregamos los encabezados y los hicimos clicables usando la función ng-click para que pudiéramos ordenar la tabla de los encabezados.

Luego creamos los datos que queríamos dentro de la tabla en forma de matriz y los declaramos dentro de la función $scope; esto nos permite agregarle la funcionalidad de ordenar usando la función $scope.sort.

Producción:

Ordenar tabla usando el modelo ng

Conclusión

Gracias a la flexibilidad del marco Angular, contamos con excelentes opciones para ayudarnos a crear tablas con la funcionalidad de clasificación.

Oluwafisayo Oluwatayo avatar Oluwafisayo Oluwatayo avatar

Fisayo is a tech expert and enthusiast who loves to solve problems, seek new challenges and aim to spread the knowledge of what she has learned across the globe.

LinkedIn

Artículo relacionado - Angular Table