Angular: Search bar in TypeScript table

微笑、不失礼 提交于 2019-12-02 03:56:33

问题


I have done a simple CRUD application, now I have to add a Search Bar that filters my table and show me the rows with the same letters that I digit.

I don't know what to do in my component, I saw different things with pipes and filter but I couldn't adapt them to my project.

I would like to know if there is a method that I can implement to my component.ts without creating a new one.

COMPONENT.HTML

<div class="container">
  <ul class="table-wrapper">
    <div class="table-title">
      <div class="row">
        <div class="col-sm-4">
          <button *ngIf="metadata && metadata.addMD" (click)="addFunc(metadata)">{{metadata.addMD.label}}</button>
          <div class="show-entries">
            <span>Show</span>
            <label>
              <select [(ngModel)]="pageSize">
                <option *ngFor="let maxPerPage of rowsOnPageSet"
                        (click)="maxElements(maxPerPage)">{{maxPerPage}}</option>
              </select>
            </label>
            <span>users</span>
          </div>
        </div>

        <div class="col-sm-4">
          <h2 class="text-center">Users <b>Details</b></h2>
        </div>

        <div class="col-sm-4">
          <div class="search-box">
            <div class="input-group">
              <span class="input-group-addon"><i class="material-icons">&#xE8B6;</i></span>
--> //HERE I HAVE TO ADD THE FUNCTION OR SOMETHING ELSE
             <input type="text" class="form-control" [(ngModel)]="searchVal"
                 (ngModelChange)='checkSearchVal()'  placeholder="Search&hellip;">
            </div>
          </div>
        </div>
      </div>
    </div>

    <table class="table table-bordered">
      <thead>
      <tr>
        <th *ngFor="let col of columns" (click)="sortTable(col)">{{col}}
          <i *ngIf="col === columnSorted && !direction" class="material-icons">keyboard_arrow_up</i>
          <i *ngIf="col === columnSorted && direction" class="material-icons">keyboard_arrow_down</i>
        </th>
        <th>Actions</th>
      </tr>
      </thead>
      <tbody>
      <tr *ngFor="let user of users | paginate: {itemsPerPage: pageSize,
                                               currentPage: page,
                                               totalItems: users.length}">
        <td *ngFor="let col of columns">{{user[col]}}</td>
        <td>
          <button [ngClass]="getClassCondition(act.actionType)" *ngFor="let act of actions"
                  (click)="actionFunc(act, user)">{{act.label}}</button>

        </td>

      </tr>
      </tbody>
    </table>

    <div align="center">
      <!--<div class="hint-text">Showing <b>{{totUsersPerPage}}</b> out of <b>{{users.length}}</b> entries</div>-->
      <ul align="center">
        <pagination-controls (pageChange)="pageChanged($event)"></pagination-controls>
      </ul>
    </div>

  </ul>
</div>

COMPONENT.TS, here I have to create the right method that works for my app.

    export class DynamicTableComponent implements OnInit {

  constructor(private userService: UserService,
              private resourcesService: ResourcesService,
              private router: Router) {
  }

  @Input()
  users = [];
  @Input()
  columns: string[];
  @Input()
  actions = [];
  @Input()
  metadata: any;
  @Input()
  class;

  direction = false;
  columnSorted = '';
  public rowsOnPageSet = ['5', '10', '15', '20', '25'];
  page = 1;
  private pageSize = 5;
  searchVal = '';

  /*totalPages = Math.trunc(this.users.length / this.pageSize);
  totUsersPerPage = this.pageSize;*/

  ngOnInit() {
  }

  actionFunc(action, element: any) {
    if (action.actionType === 'DELETE') {
        /*...*/
      }
    }
    if (action.actionType === 'GO_TO') {
        /*...*/
    }
  }

  addFunc(metadata) {
    if (metadata.addMD.actionType === 'ADD_TO') {
       /*...*/
    }
  }

  maxElements(maxPerPage) {
    this.rowsOnPageSet = maxPerPage;
  }

  sortTable(param) {
    /*...*/
  }

  getClassCondition(act) {
    return act === 'DELETE' ? this.class = 'btn btn-danger' : 'btn btn-primary';
  }

  pageChanged($event: number) {
     /*...*/
  }

checkSearchVal() {
    this.users.slice();
    const filteredUsers: User[] = [];
    if (this.searchVal && this.searchVal !== '') {
      for (const selectedUser of this.users) {
        if (selectedUser.firstName.toLowerCase().search(this.searchVal.toLowerCase()) !== -1 ||
          selectedUser.lastName.toLowerCase().search(this.searchVal.toLowerCase()) !== -1) {
          filteredUsers.push(selectedUser);
        }
      }
      this.users = filteredUsers.slice();
    }
  }

}

DATA STRUCTURE: in.memory-data.service.ts

import { InMemoryDbService } from 'angular-in-memory-web-api';
import { User } from './user';
import { Injectable } from '@angular/core';

export const COLUMNS = ['id', 'firstName', 'lastName', 'age'];

@Injectable({
  providedIn: 'root',
})
export class InMemoryDataService implements InMemoryDbService {
  createDb() {
    const USERS = [
      {id: 1, firstName: 'Sergio', lastName: 'Rios', age: 23},
      {id: 2, firstName: 'Alessandro', lastName: 'Amodeo', age: 23},
      {id: 3, firstName: 'Antonio', lastName: 'Vitolo', age: 23},
      {id: 4, firstName: 'Andrea', lastName: 'Bellati', age: 24},
      {id: 5, firstName: 'Yvette', lastName: 'Arevalo Godier', age: 42},
      {id: 6, firstName: 'Federico', lastName: 'Belloni', age: 41},
      {id: 7, firstName: 'Claudio', lastName: 'Tornese', age: 24},
      {id: 8, firstName: 'Diana', lastName: 'Budascu', age: 25},
      {id: 9, firstName: 'Veronica', lastName: 'Moreira', age: 25},
      {id: 10, firstName: 'Sirak', lastName: 'Guida', age: 25},
      {id: 11, firstName: 'Marina', lastName: 'Righetti', age: 22},
      {id: 12, firstName: 'Giorgia', lastName: 'Secchi', age: 22},
      {id: 13, firstName: 'Simone', lastName: 'Bocallari', age: 24},
    ];
    return {USERS};
  }
}

user.ts

export class User {
  id: number;
  firstName: string;
  lastName: string;
  age: number;
}

回答1:


I saw that you got your answer... here is another approach for what it is worth... as discussed in the comments...

checkSearchVal() {
    this.USERS = masterUSERS.slice();
    let filteredUsers: User[] = [];
    if (this.searchVal && this.searchVal != '') {

    /* NORMAL FOR
      for(var i=0; i<this.USERS.length; i++ ){
        if(this.USERS[i].firstName.toLowerCase().search(this.searchVal.toLowerCase()) != -1 || this.USERS[i].lastName.toLowerCase().search(this.searchVal.toLowerCase()) != -1 ){
          filteredUsers.push(this.USERS[i])
        }
      }
    */
    /* FOR EACH
      this.USERS.forEach((selectedUser) => {
        if (selectedUser.firstName.toLowerCase().search(this.searchVal.toLowerCase()) != -1 ||
          selectedUser.lastName.toLowerCase().search(this.searchVal.toLowerCase()) != -1) {
          filteredUsers.push(selectedUser);
        }
      })
    */

    /*  FOR OF */
    for (let selectedUser of this.USERS) {
        if (selectedUser.firstName.toLowerCase().search(this.searchVal.toLowerCase()) != -1 ||
          selectedUser.lastName.toLowerCase().search(this.searchVal.toLowerCase()) != -1) {
          filteredUsers.push(selectedUser);
        }
    }

      this.USERS = filteredUsers.slice();
    }
  }

update: moved the this.USERS = filteredUsers.slice(); inside the IF

update:2: same code with forEach and For-Of (to get rid of the TSLint error)




回答2:


Just create a PIPE.ts file to filter the table:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ 
    name: 'filterAll'
})
export class FilterPipe implements PipeTransform {
  transform(value: any, searchText: any): any {
    if(!searchText) {
      return value;
    }
    return value.filter((data) => this.matchValue(data,searchText)); 
  }

  matchValue(data, value) {
    return Object.keys(data).map((key) => {
       return new RegExp(value, 'gi').test(data[key]);
    }).some(result => result);
  }
 }

Add the FilterPipe to app.module.ts in declarations and add this to your component.html:

  <form id="searchForm">
    <div class="form-group">
        <div class="input-group" id="filterAll">
          <div class="input-group-addon"><i class="glyphicon glyphicon-search"></i></div>
          <input type="text" class="form-control" name="searchString" placeholder="Search..." [(ngModel)]="searchString">
        </div>
    </div>
</form>

then you add a pipe to the TR of your table like this:

 <tr *ngFor="let user of users | paginate: {itemsPerPage: pageSize,
                                           currentPage: page,
                                           totalItems: users.length} | filterAll: searchString">

I forgot about the component.ts file sorry: You need to put the searchString variable as:

public searchString: string;


来源:https://stackoverflow.com/questions/55060545/angular-search-bar-in-typescript-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!