Top

Tables


# First Name Last Name Username Role Country
1 Alexander Orton @mdorton Admin USA
2 John Deo Deo @johndeo User USA
3 Randy Orton the Bird @twitter admin UK
4 Randy Mark Ottandy @mdothe user AUS
5 Ram Jacob Thornton @twitter admin IND
<div class="table-responsive">
  <table class="table">
    <thead>
      <tr>
        <th scope="col">#</th>
        <th scope="col">First Name</th>
        <th scope="col">Last Name</th>
        <th scope="col">Username</th>
        <th scope="col">Role</th>
        <th scope="col">Country</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">1</th>
        <td>Alexander</td>
        <td>Orton</td>
        <td>@mdorton</td>
        <td>Admin</td>
        <td>USA</td>
      </tr>
      <tr>
        <th scope="row">2</th>
        <td>John Deo</td>
        <td>Deo</td>
        <td>@johndeo</td>
        <td>User</td>
        <td>USA</td>
      </tr>
      <tr>
        <th scope="row">3</th>
        <td>Randy Orton</td>
        <td>the Bird</td>
        <td>@twitter</td>
        <td>admin</td>
        <td>UK</td>
      </tr>
      <tr>
        <th scope="row">4</th>
        <td>Randy Mark</td>
        <td>Ottandy</td>
        <td>@mdothe</td>
        <td>user</td>
        <td>AUS</td>
      </tr>
      <tr>
        <th scope="row">5</th>
        <td>Ram Jacob</td>
        <td>Thornton</td>
        <td>@twitter</td>
        <td>admin</td>
        <td>IND</td>
      </tr>
    </tbody>
  </table>
</div>
Name Position Office Age Start date Salary
Tiger Nixon System Architect Edinburgh 61 2011/04/25 $320,800
Garrett Winters Accountant Tokyo 63 2011/07/25 $170,750
 <div class="card">
  <form class="table-responsive theme-scroollbar">
        <div class="card-body">
            <div class="card-header">
                <h3>Individual column searching (text inputs) </h3><span>The searching functionality provided by
                    DataTables is useful for quickly search through the information in the table - however the search is
                    global,
                    and you may wish to present controls that search on specific columns.</span>
            </div>
            <div class="dataTables_wrapper">
                <div class="d-flex justify-content-between p-2">
                    <div class="dataTables_length" id="basic-6_length">
                        <label>Show
                            <select name="pageSize" [(ngModel)]="service.pageSize">
                                <option [ngValue]="10">10</option>
                                <option [ngValue]="15">15</option>
                                <option [ngValue]="20">20</option>
                                <option [ngValue]="25">25</option>
                            </select> entries
                        </label>
                    </div>
                    <div class="mb-3 row">
                        <label for="table-complete-search" class="col-xs-3 col-sm-auto col-form-label">Search:</label>
                        <div class="col-xs-3 col-sm-auto">
                            <input id="table-complete-search" type="text" class="form-control" name="searchTerm"
                                [(ngModel)]="service.searchTerm" autocomplete="off" />
                        </div>
                        @if(service.loading$ | async){
                        <span class="col col-form-label">Loading...</span>
                        }
                    </div>
                </div>
                <table class="display table table-striped table-hover table-light">
                    <thead>
                        <tr>
                            <th scope="col">#</th>
                            <th scope="col" sortable="name" (sort)="onSort($event)">Name</th>
                            <th scope="col" sortable="position" (sort)="onSort($event)">Position</th>
                            <th scope="col" sortable="salary" (sort)="onSort($event)">Salary</th>
                            <th scope="col" sortable="office" (sort)="onSort($event)">Office</th>
                            <th scope="col" sortable="extn" (sort)="onSort($event)">Extn</th>
                            <th scope="col" sortable="email" (sort)="onSort($event)">Email</th>
                            <th scope="col">Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        @for(data of tableData$ | async; track data; let i = $index){
                        <tr>
                            <th scope="row">{{ i + 1 + ((service.page - 1) * service.pageSize)}}</th>
                            <td>
                                <ngb-highlight [result]="data.name" [term]="service.searchTerm"></ngb-highlight>
                            </td>
                            <td>
                                <ngb-highlight [result]="data.position" [term]="service.searchTerm"></ngb-highlight>
                            </td>
                            <td>
                                <ngb-highlight [result]="data.salary|number"
                                    [term]="service.searchTerm"></ngb-highlight>
                            </td>
                            <td>
                                <ngb-highlight [result]="data.office" [term]="service.searchTerm"></ngb-highlight>
                            </td>
                            <td>
                                <ngb-highlight [result]="data.extn|number" [term]="service.searchTerm"></ngb-highlight>
                            </td>
                            <td>
                                <ngb-highlight [result]="data.email" [term]="service.searchTerm"></ngb-highlight>
                            </td>
                            <td>
                                <ul class="action">
                                    <i class="fa fa-eye font-primary pe-2"></i>
                                    <i class="icofont icofont-close-circled font-danger ps-2"></i>
                                </ul>
                            </td>
                        </tr>
                        }
                        @empty{
                        <tr class="odd">
                            <td colspan="10" class="dataTables_empty" style="text-align: center;">
                                <div class="search-not-found text-center">
                                    <p>Sorry, No records found</p>
                                </div>
                            </td>
                        </tr>
                        }
                    </tbody>
                </table>
                <div class="d-flex justify-content-between p-2">
                    <div class="dataTables_info">
                        <span class="mt-4">Showing {{ getStartingIndex() }} to {{ getEndingIndex() }} of {{
                            filteredData.length }} entries</span>
                    </div>
                    <ngb-pagination class="ms-3" [collectionSize]="( total$ | async)!" [(page)]="service.page"
                        [pageSize]="service.pageSize">
                    </ngb-pagination>
                </div>
            </div>
        </div>
    </form>
</div> 
To use datatable you have to add code .ts file fills

  import { CommonModule, DecimalPipe } from '@angular/common';
  import { Component, inject, viewChildren } from '@angular/core';
  import { FormsModule, ReactiveFormsModule } from '@angular/forms';
  
  import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
  import { Observable } from 'rxjs';
  
  import {
    NgbdSortableHeaderDirective,
    SortEvent,
  } from '../../../shared/directives/sortable.directive';
  import { supportDB } from '../../../shared/interface/support';
  import { TableService } from '../../../shared/services/table.service';
  
  @Component({
    selector: 'app-data-table',
    imports: [CommonModule, FormsModule, NgbdSortableHeaderDirective, ReactiveFormsModule, NgbModule],
    templateUrl: './data-table.html',
    styleUrl: './data-table.scss',
    providers: [TableService, DecimalPipe],
  })
  export class DataTables {
    public service = inject(TableService);
  
    public tableData$: Observable = this.service.supportdata$;
    public total$: Observable = this.service.total$;
    public Data: supportDB[];
  
    readonly headers = viewChildren(NgbdSortableHeaderDirective);
  
    ngOnInit() {
      this.tableData$.subscribe(res => {
        this.Data = res;
      });
    }
  
    onSort({ column, direction }: SortEvent) {
      this.headers().forEach(header => {
        if (header.sortable() !== column) {
          header.currentDirection.set('');
        }
      });
  
      this.service.sortColumn = column;
      this.service.sortDirection = direction;
    }
  }
  

you have use this services fill

  import { DecimalPipe } from '@angular/common';
  import { inject, Injectable } from '@angular/core';
  
  import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
  import { debounceTime, delay, switchMap, tap } from 'rxjs/operators';
  
  import { SUPPORTDB } from '../../shared/data/table/SupportTdb';
  import { SortColumn, SortDirection } from '../directives/sortable.directive';
  import { supportDB } from '../interface/support';
  
  interface SearchResult {
    Details: supportDB[];
    total: number;
  }
  
  interface State {
    page: number;
    pageSize: number;
    searchTerm: string;
    sortColumn: SortColumn;
    sortDirection: SortDirection;
  }
  
  const compare = (v1: string | number, v2: string | number) => (v1 < v2 ? -1 : v1 > v2 ? 1 : 0);
  
  function sort(countries: supportDB[], column: SortColumn, direction: string): supportDB[] {
    if (direction === '' || column === '') {
      return countries;
    } else {
      return [...countries].sort((a, b) => {
        const res = compare(a[column], b[column]);
        return direction === 'asc' ? res : -res;
      });
    }
  }
  
  function matches(support: supportDB, term: string) {
    return (
      support.name.toLowerCase().includes(term.toLowerCase()) ||
      support.position.toLowerCase().includes(term.toLowerCase()) ||
      support.office.toLowerCase().includes(term.toLowerCase()) ||
      support.email.toLowerCase().includes(term.toLowerCase())
    );
  }
  
  @Injectable({ providedIn: 'root' })
  export class TableService {
    public pipe = inject(DecimalPipe);
    private _loading$ = new BehaviorSubject(true);
    private _search$ = new Subject();
    private _data$ = new BehaviorSubject([]);
    private _total$ = new BehaviorSubject(0);
  
    private _state: State = {
      page: 1,
      pageSize: 10,
      searchTerm: '',
      sortColumn: '',
      sortDirection: '',
    };
  
    constructor() {
      this._search$
        .pipe(
          tap(() => this._loading$.next(true)),
          debounceTime(200),
          switchMap(() => this._search()),
          delay(200),
          tap(() => this._loading$.next(false)),
        )
        .subscribe(result => {
          this._data$.next(result.Details);
          this._total$.next(result.total);
        });
  
      this._search$.next();
    }
  
    get supportdata$() {
      return this._data$.asObservable();
    }
    get total$() {
      return this._total$.asObservable();
    }
    get loading$() {
      return this._loading$.asObservable();
    }
    get page() {
      return this._state.page;
    }
    get pageSize() {
      return this._state.pageSize;
    }
    get searchTerm() {
      return this._state.searchTerm;
    }
  
    set page(page: number) {
      this._set({ page });
    }
    set pageSize(pageSize: number) {
      this._set({ pageSize });
    }
    set searchTerm(searchTerm: string) {
      this._set({ searchTerm });
    }
    set sortColumn(sortColumn: SortColumn) {
      this._set({ sortColumn });
    }
    set sortDirection(sortDirection: SortDirection) {
      this._set({ sortDirection });
    }
  
    private _set(patch: Partial) {
      Object.assign(this._state, patch);
      this._search$.next();
    }
  
    private _search(): Observable {
      const { sortColumn, sortDirection, pageSize, page, searchTerm } = this._state;
  
      // 1. sort
      let Details = sort(SUPPORTDB, sortColumn, sortDirection);
  
      // 2. filter
      Details = Details.filter(support => matches(support, searchTerm));
      const total = Details.length;
  
      // 3. paginate
      Details = Details.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
      return of({ Details, total });
    }
  }
  
you have use this directive

  import { Directive, HostBinding, HostListener, input, output, signal } from '@angular/core';

  import { supportDB } from '../interface/support';
  
  export type SortColumn = keyof supportDB | '';
  export type SortDirection = 'asc' | 'desc' | '';
  const rotate: { [key: string]: SortDirection } = { asc: 'desc', desc: '', '': 'asc' };
  
  export interface SortEvent {
    column: SortColumn;
    direction: SortDirection;
  }
  
  @Directive({
    standalone: true,
    selector: 'th[sortable]',
    host: {
      '[class.asc]': 'direction === "asc"',
      '[class.desc]': 'direction === "desc"',
      '(click)': 'rotate()',
    },
  })
  export class NgbdSortableHeaderDirective {
    readonly sortable = input('');
    readonly direction = input(''); 
  
  
    public currentDirection = signal(this.direction());
  
    // Output event
    readonly sort = output();
    @HostBinding('class.asc')
    get isAsc() {
      return this.currentDirection() === 'asc';
    }
  
    @HostBinding('class.desc')
    get isDesc() {
      return this.currentDirection() === 'desc';
    }
  
    @HostListener('click')
    rotateColumn() {
      this.currentDirection.set(rotate[this.currentDirection()]);
      this.sort.emit({ column: this.sortable(), direction: this.currentDirection() });
    }
  }