【问题标题】:Implementing NGX Datatable filtering on all columns在所有列上实现 NGX 数据表过滤
【发布时间】:2017-12-19 17:57:17
【问题描述】:

我一直试图让这个工作没有运气。我一直在参考这些资源寻求帮助: http://swimlane.github.io/ngx-datatable/#filter
https://github.com/swimlane/ngx-datatable/blob/master/demo/basic/filter.component.ts

基本上我只想让我的过滤器应用于多个列,而不是实现代码来处理每一列。 (有些数据表有​​ 20 多列!)

示例代码:

//HTML
  <input type='text' placeholder='Filter' (keyup)='updateFilter($event.target.value)' />

  <ngx-datatable
    class="material"
    columnMode="force"
    [columns]="gridProperties.FilteredColumns"
    [footerHeight]="50"
    [loadingIndicator]="gridLoadingIndicator"
    [rows]="filteredList"
    [scrollbarH]="false"
    [scrollbarV]="true"
    [selected]="selectedItem"
    [selectionType]="'single'"
    style="min-height:400px;">
  </ngx-datatable>

//TYPESCRIPT
  public items: Item[];

  updateFilter(filterValue) {
    const lowerValue = filterValue.toLowerCase();

    this.filteredList = this.items.filter(item => item.name.toLowerCase().indexOf(lowerValue) !== -1 || !lowerValue);
  }

这里我显然只是在处理我的 items 数组的 'name' 属性的过滤。这很有效,但就像我提到的那样,如果网格包含许多列,我想要一种方法来处理所有这些列。感谢您提供任何帮助或提示。

【问题讨论】:

标签: angular typescript ngx-datatable


【解决方案1】:

在使用上述一些答案时出现了一些问题,我正在添加我自己的...

首先最好将键存储在全局变量中,因为每次迭代都会覆盖内容。

问题已解决...

  1. 如果数据是通过输入推送的,我们尤其需要重置键 如果没有数据开始。

  2. 将所有内容存储在临时变量中以始终保留原始数据。**

我在这里发布我的全部使用情况..

import {
  Component,
  ElementRef,
  EventEmitter,
  Input,
  OnChanges,
  OnInit,
  Output,
  SimpleChanges,
  ViewChild,
} from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'verasci-data-table',
  templateUrl: './data-table.component.html',
  styleUrls: ['./data-table.component.scss'],
})
export class DataTableComponent implements OnInit, OnChanges {
  @ViewChild('table') table;
  @Input() rows;
  @Input() columns;
  @Input() searchBar;
  keys;
  temp: Array<any>;
  @Output() selectEvent$ = new EventEmitter();
  selected = [];
  readonly pageLimit = 10;
  readonly headerHeight = 50;
  readonly rowHeight = 50;

  constructor(private readonly el: ElementRef, private readonly router: Router) { }

  async ngOnInit() {
    this.temp = this.rows;
    this.keys = this.rows[0] ? Object.keys(this.rows[0]) : null;
    setTimeout(() => { this.dataLoaded = true; }, 200);
  }

  // we need to reset keys and temp data if data is pushed to the table.
  ngOnChanges(changes: SimpleChanges) {
    this.keys = this.rows[0] ? Object.keys(this.rows[0]) : null;
    this.temp = this.rows;
  }       

  filterSingle(event) {
    const val = event.target.value.toLowerCase();

    // filter our data
    const temp = this.temp.filter((d) => {
      return d.sponsor.toLowerCase().indexOf(val) !== -1 || !val;
    });

    // update the rows
    this.rows = temp;
    // Whenever the filter changes, always go back to the first page
    this.table.offset = 0;
  }

  filterMulti(event) {
    // get the value of the key pressed and make it lowercase
    const val = event.target.value.toLowerCase();
    // get the amount of columns in the table
    const colsAmt = this.columns.length;
    // get the key names of each column in the dataset
    const keys = this.keys; // just need to keys from the first set of rw
    // filter our data
    const temp = this.temp.filter(item => {
    // iterate through each row's column data
    for (let i = 0; i < colsAmt; i++) {
    // check for a match on properties that are not null
      if (item[keys[i]] != null && (item[keys[i]].toString().toLowerCase().indexOf(val) !== -1 || !val)) {
        // found match, return true to add to result set
        return true;
      }
     }
   });
    // update the rows
    this.rows = temp;
    // Whenever the filter changes, always go back to the first page
    this.table.offset = 0;
  }

  onSelect({ selected }) {
    this.selectEvent$.emit({ selected: selected[0] });
  }

}

【讨论】:

    【解决方案2】:

    此答案改进了 Cole Paciano 的现有答案:

    • 要搜索的列名只创建一次,而不是在每次按下键时创建
    • 具有null 值的单元格得到正确处理(无控制台错误)
    • 显示完整的行(因为过滤器应用于行数组)
    • 也可以手动指定要搜索的列名以仅包含其中的一些(排除 guid、id 等)

    以下是步骤

    template (html) 文件中添加带有keyup 处理程序的输入

    Search:
    <input type="text" (keyup)='filterDatatable($event)'>
    <ngx-datatable
        class="material"
        [rows]="rows"
        [columns]="columns"
        headerHeight="35"
        rowHeight ="35">
    </ngx-datatable>
    

    component 中添加以下filteredDatacolumnsWithSearch

    export class ListParkingsComponent implements OnInit {
      columns = [];
      rows = [];
      filteredData = [];
      columnsWithSearch : string[] = [];
    
    ngOnInit() {
        this.rows = getData() ; //recover data from API/database/datasource
        this.filteredData = this.rows;
        // for specific columns to be search instead of all you can list them by name
        this.columnsWithSearch = Object.keys(this.rows[0]);
    }
    
    getData() {
       //your current logic to fill the rows of the table
    }
    
    // filters results
    filterDatatable(event){
        // get the value of the key pressed and make it lowercase
        let filter = event.target.value.toLowerCase();
    
        // assign filtered matches to the active datatable
        this.rows = this.filteredData.filter(item => {
          // iterate through each row's column data
          for (let i = 0; i < this.columnsWithSearch.length; i++){
            var colValue = item[this.columnsWithSearch[i]] ;
    
            // if no filter OR colvalue is NOT null AND contains the given filter
            if (!filter || (!!colValue && colValue.toString().toLowerCase().indexOf(filter) !== -1)) {
              // found match, return true to add to result set
              return true;
            }
          }
        });
        // TODO - whenever the filter changes, always go back to the first page
        //this.table.offset = 0;
    }
    

    【讨论】:

      【解决方案3】:

      同时将数据存储在rows列表中,同时初始化perttemp列表,以便过滤后获取

      updateFilter(event) {
      
          const val = event.target.value.toLowerCase();
          if(val) {
              this.temp = this.rows;
              // filter our data
              const temp = this.temp.filter(function (d) {
                return ( d.name.toLowerCase().indexOf(val) !== -1 || d.email.toLowerCase().indexOf(val) !== -1 || !val);
              });
              this.rows = temp;
          }
          else
          {
              this.rows = this.perttemp;
          }
      }
      

      【讨论】:

        【解决方案4】:

        您可能会得到帮助

         <input
                type="text"
                style="padding:8px;margin:15px auto;width:30%;"
                placeholder="Type to filter the name column..."
                (keyup)="updateFilter($event)"
              />
              <ngx-datatable
                #table
                class="material"
                [columns]="columns"
                [columnMode]="ColumnMode.force"
                [headerHeight]="50"
                [footerHeight]="50"
                rowHeight="auto"
                [limit]="10"
                [rows]="rows"
              >
              </ngx-datatable>
        
        
        
        
        updateFilter(event) {
            const val = event.target.value.toLowerCase();
        
            // filter our data
            const temp = this.temp.filter(function(d) {
              return d.name.toLowerCase().indexOf(val) !== -1 ||
                d.address.toLowerCase().indexOf(val) !== -1 ||
                d.gender.toLowerCase().indexOf(val) !== -1 || !val;
            });
        
            // update the rows
            this.rows = temp;
            // Whenever the filter changes, always go back to the first page
            this.table.offset = 0;
          }
        

        https://github.com/swimlane/ngx-datatable/blob/master/src/app/basic/dark-theme.component.ts

        【讨论】:

          【解决方案5】:
          import { DatatableComponent } from '@swimlane/ngx-datatable';
          ViewChild(DatatableComponent) table: DatatableComponent;
          
             updateFilter(event) {
              const val = event.target.value.toLowerCase();
              var returnData: any;
              // filter our data
              const temp = this.temp.filter(function (d) {
                if (d.yourFirstColumnName.toLowerCase().indexOf(val) !== -1 || !val) {
                  returnData = d.user_name.toLowerCase().indexOf(val) !== -1 || !val;
                } else if (d.yourSecondColumnName.toLowerCase().indexOf(val) !== -1 || !val) {
                  returnData = d.notes_title.toLowerCase().indexOf(val) !== -1 || !val;
          
                }
                return returnData;
              });
          
           <input placeholder="Search Order" (keyup)='updateFilter($event)'>
          

          【讨论】:

            【解决方案6】:
             updateFilter(event) {
                const val = event.target.value.toLowerCase();
                const temp = this.temp.filter(index => {
                  return (index.name.toLowerCase().indexOf(val) !== -1 ||
                    index.company.toLowerCase().indexOf(val) !== -1 ||
                    index.gender.toLowerCase().indexOf(val) !== -1 ||
                    !val);
                });
                this.company = temp;
                this.table.offset = 0;
              }
            

            【讨论】:

              【解决方案7】:

              使用示例 TS 文件进行过滤 (https://github.com/swimlane/ngx-datatable/blob/master/demo/basic/filter.component.ts) 作为基础,我能够成功地使其动态过滤所有列(它将过滤所有列而无需指定它们)。我已经包含了我认为所有必要的部分,但我也尽可能地精简了代码以使其更容易理解。

              HTML

              <ngx-datatable
               #table
               class="material striped scroll-vertical"
               [rows]="data"
               [columns]="cols"
               [columnMode]="'force'"
               [headerHeight]="35"
               [footerHeight]="35"
               [rowHeight]="'auto'"
               [limit]="pageSize"
               [selectionType]="'single'">
              
              <input type="text" (keyup)='filterDatatable($event)'>
              

              打字稿

              cols = [{name:'First Name'},{name:'Last Name'},{name:'Address'}];
              data = [];
              filteredData = [];
              
              // dummy data for datatable rows
              dummyData = [
                {firstName:'Daenarys',lastName:'Targaryen',address:'Dragonstone'},
                {firstName:'Sansa',lastName:'Stark',address:'Winterfell'},
                {firstName:'Cersei',lastName:'Lannister',address:'Kings Landing'},
                {firstName:'Brienne',lastName:'Tarth',address:'Sapphire Island'},
                {firstName:'Lyanna',lastName:'Mormont',address:'Bear Island'},
                {firstName:'Margaery',lastName:'Tyrell',address:'Highgarden'}
              ]
              
              ngOnInit(){
                // populate datatable rows
                this.data = this.dummyData;
                // copy over dataset to empty object
                this.filteredData = this.dummyData;
              }
              
              // filters results
              filterDatatable(event){
                // get the value of the key pressed and make it lowercase
                let val = event.target.value.toLowerCase();
                // get the amount of columns in the table
                let colsAmt = this.cols.length;
                // get the key names of each column in the dataset
                let keys = Object.keys(this.dummyData[0]);
                // assign filtered matches to the active datatable
                this.data = this.filteredData.filter(function(item){
                  // iterate through each row's column data
                  for (let i=0; i<colsAmt; i++){
                    // check for a match
                    if (item[keys[i]].toString().toLowerCase().indexOf(val) !== -1 || !val){
                      // found match, return true to add to result set
                      return true;
                    }
                  }
                });
                // whenever the filter changes, always go back to the first page
                this.table.offset = 0;
              }
              

              【讨论】:

              • 我已经改进了这个答案以过滤 ROWS 数组而不是 COLUMNS 数组,正确处理具有 NULL 值的 CELLS 以及其他改进 - 请参阅下面的答案。
              • 当局部变量从不重新赋值时,考虑使用const 而不是let
              【解决方案8】:

              这是您的多列过滤代码示例:

              updateFilter(filter: string): void {
              
                const val = filter.trim().toLowerCase();
              
                this.filteredList = this.items.slice().filter((item: any) => {
                  let searchStr = '';
                  for (let i = 0; i < this.gridProperties.FilteredColumns.length; i++) {
                    searchStr += (item[this.gridProperties.FilteredColumns[i]]).toString().toLowerCase();
                  }
                  return searchStr.indexOf(val) !== -1 || !val;
                });
              }
              

              如果我没有犯任何错误,它应该可以正常工作。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-01-01
                • 1970-01-01
                • 2017-05-19
                • 2014-03-11
                • 1970-01-01
                • 2020-09-12
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多