<repo_name>Melo93/AngularTable<file_sep>/src/app/generic-table/filter.pipe.ts
import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {

  transform(value: any[], search: string, column?: string): any[] {
    if (!value) {
      return [];
    }
    if (!search) {
      return value;
    }

    search = search.toLocaleLowerCase();
    if(column === ''){
    return value.filter(
      val => Object.keys(val).some(i => {
        if (typeof val[i] === 'string') {
          return val[i].toLowerCase().includes(search.toLocaleLowerCase());
          }
        }));
    } else {
      return value.filter(
        val => val[column].toLowerCase().includes(search.toLocaleLowerCase())
      );
    }
  }

}
<file_sep>/src/app/pager.service.ts
import {Injectable} from '@angular/core';

@Injectable()
export class PagerService {

  constructor() {}

  getPager(totalItems: number, currentPage: number = 1, pageSize: number = 2, maxPages: number = 10) {

    const totalPages = Math.ceil(totalItems / pageSize);

    if (currentPage < 1) {
      currentPage = 1;
    } else if (currentPage > totalPages) {
      currentPage = totalPages;
    }

    let startPage: number;
    let endPage: number;

    if (totalPages <= maxPages) {
      // pagine totali inferiori a maxPages, quindi mostra tutte le pagine
      startPage = 1;
      endPage = totalPages;
    //  console.log('pagine totali inferiori a maxpages: ' + startPage + ' - ' + endPage);
    } else {
      // pagine totali più del massimo, quindi calcola le pagine iniziale e finale
      const maxPagesBeforeCurrentPage = Math.floor(maxPages / 2);
      const maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1;
      // console.log('pagine totali più del massimo' + maxPagesBeforeCurrentPage + ' - ' + maxPagesAfterCurrentPage);
      if (currentPage <= maxPagesBeforeCurrentPage) {
        // pagina corrente vicino alla pagina iniziale
        startPage = 1;
        endPage = maxPages;
        // console.log('Pagina vicino ad iniziale ' +  startPage + ' - ' + endPage);
      } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) {
        // pagina corrente vicino alla pagina finale
        startPage = totalPages - maxPages + 1;
        endPage = totalPages;
       // console.log('Pagina vicino ad finale ' +  startPage + ' - ' + endPage);
      } else {
        // pagina corrente nel mezzo
        startPage = currentPage - maxPagesBeforeCurrentPage;
        endPage = currentPage + maxPagesAfterCurrentPage;
       // console.log('Pagina nel mezzo ' +  startPage + ' ' + endPage);
      }
    }

    // calcola index iniziale e finale
    // tslint:disable-next-line:no-debugger
    debugger;
    const startIndex = (currentPage - 1) * pageSize;
    const intPageSize: number = +pageSize;
    const endIndex = Math.min(startIndex + intPageSize - 1, totalItems - 1);

    // Creo l'array delle Pagine
    const pages = Array.from(Array((endPage + 1) - startPage).keys()).map(i => startPage + i);

    // Setto le proprietà dell'oggetto da restituire alle view
    return {
      totalItems,
      currentPage,
      pageSize,
      totalPages,
      startPage,
      endPage,
      startIndex,
      endIndex,
      pages
    };
  }
}
<file_sep>/src/app/table/table.component.ts
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {Header} from '../header';
import {TableContent} from '../table-content';

import car from '../car.json';
import header from '../header.json';

@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css']
})

export class TableComponent implements OnInit {

  data: any = car;
  header: Header[] = header;
  tableContent: TableContent;

  constructor() {

  }

  ngOnInit() {

    this.tableContent = {
      header: this.header,
      data: this.data
    };

  }


}
<file_sep>/src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import { AppComponent } from './app.component';
import { GenericTableComponent } from './generic-table/generic-table.component';
import { TableComponent } from './table/table.component';
import {FormsModule} from '@angular/forms';
import {PagerService} from './pager.service';
import { FilterPipe } from './generic-table/filter.pipe';
import { AngularFontAwesomeModule } from 'angular-font-awesome';


@NgModule({
  declarations: [
    AppComponent,
    GenericTableComponent,
    TableComponent,
    FilterPipe
  ],
  imports: [
    BrowserModule,
    FormsModule,
    NgbModule,
    AngularFontAwesomeModule
  ],
  providers: [PagerService],
  bootstrap: [AppComponent]
})
export class AppModule { }
<file_sep>/src/app/table-content.ts

export class TableContent {
  header: any;
  data: any;
}
<file_sep>/src/app/header.ts
export class Header {
  columnValue: string;
  columnLabel: string;
}
<file_sep>/src/app/generic-table/generic-table.component.ts
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {TableContent} from '../table-content';
import * as _ from 'lodash';
import {PagerService} from '../pager.service';
import {Action} from 'rxjs/internal/scheduler/Action';

@Component({
  selector: 'app-generic-table',
  templateUrl: './generic-table.component.html',
  styleUrls: ['./generic-table.component.css']
})
export class GenericTableComponent implements OnInit {

  @Input() searchBar ? = false;
  @Input() tableContent: TableContent;
  @Output('onClickAction') event = new EventEmitter();
  columnToSearch = '';
  search: string;
  icon = 'sort';
  clicked = false;

  //paginazione
  maxPageNumberSelector: number;
  responsePageObject: any = {};
  paginatedData: any[];
  isPaginated = false;
  lodash = _;


  constructor(private pagerService: PagerService) {
  }

  ngOnInit() {
  }

  setPage(page: number) {
    this.responsePageObject = this.pagerService.getPager(this.tableContent.data.length, page, this.maxPageNumberSelector);
    this.paginatedData = this.tableContent.data.slice(this.responsePageObject.startIndex, this.responsePageObject.endIndex + 1);
  }

  onClickAction(action: Action<any>, model: any, url?: string) {
    this.event.emit({action, model});

  }

  onChange($event: Event) {
    console.log(this.maxPageNumberSelector);
    this.isPaginated = true;
    this.setPage(1);
  }

  orderBy(key: string) {
    if (!this.clicked) {
      if (this.isPaginated) {
        this.paginatedData = this.tableContent.data.slice(this.responsePageObject.startIndex, this.responsePageObject.endIndex + 1);
      }
      this.icon = 'sort-up';
      this.clicked = true;
      this.tableContent.data = _.orderBy(this.tableContent.data, [key], ['asc']);
    } else {
      if (this.isPaginated) {
        this.paginatedData = this.tableContent.data.slice(this.responsePageObject.startIndex, this.responsePageObject.endIndex + 1);
      }
      this.icon = 'sort-down';
      this.clicked = false;
      this.tableContent.data = _.orderBy(this.tableContent.data, [key], ['desc']);
    }
  }
}

<file_sep>/src/app/table-content.spec.ts
import { TableContent } from './table-content';

describe('TableContent', () => {
  it('should create an instance', () => {
    expect(new TableContent()).toBeTruthy();
  });
});
