0
votes

I have this example:

https://embed.plnkr.co/iUrXZcG14lzhpD5Ofa3z/

which shows a table with its columns, what i need is building a search lookup function instead of the default filter function, so that:

if typing the full name michael then the table will be filter by michael, OR if i type the phone number then the name of michael will be filtery by michael. in other word.

There is a mapping array:

    {
key: michael,
value: michael,
tokens:{
    michael,
    mich,
    ael,
    +0912312321
    }}
    ,
    {

key:    natalie,
  value:  natalie,
tokens{
natalie
    lie
    ,
    +091212
}
    }

so instead of the defaul search function i want that the search will be looked up in that mapping object.

2

2 Answers

1
votes

Firstly, your mapping array is incorrectly formatted, change it the following:

  [{
    key: 'michael',
    value: 'michael',
    tokens: ['michael', 'mich', 'ael', '+0912312321'],
  },
  {
    key: 'natalie',
    value: 'natalie',
    tokens: ['natalie', 'lie', '+091212'],
  }]

What you need to do is create your own custom search filter. This is easy using ag-Grid, see here. With your custom filter, you then need to then decide for each row whether it should be filtered or not using mapping array.

In your doesFilterPass function in your custom filter component, your logic should look something like this:

PersonFilter.prototype.doesFilterPass = function (params) {
  // make sure each word passes separately, ie search for firstname, lastname
  var valueGetter = this.valueGetter;

  console.log(valueGetter(params))

  let acceptableFilterValues = [];
  const filterDataForValue = filterData.find(x => x.value == valueGetter(params).toLowerCase());


  if (!filterDataForValue)
  { 
    return false; 
  } 
  
  const tokensForFilterValue = filterDataForValue.tokens;

  return tokensForFilterValue.indexOf(this.filterText) > -1;
};

Take a look at this Plunker demonstration. Click on the filter icon on the name column.

1
votes

I made this StackBlitz with the modifications needed from my previous example on ng-grid filters.

You need to redefine the function doesFilterPass(...) wich is executed once per row in the table to match your desired filter:

customFilter(filterWord: string, node: RowNode): boolean {
  let data = [
    { key: 'Smith', tokens: ['Smith', 'ael', '+0912312321'] },
    { key: 'Robert', tokens: ['Robert', 'rob', '457891187'] }
  ];

  let rowData = null;

  data.forEach((record => {
    if (record.key === this.valueGetter(node).toString()) {
      rowData = record;
    }
  }));

  return rowData.tokens.some((token) => {
    return token.toLowerCase().indexOf(filterWord) >= 0;
  });
}

doesFilterPass(params: IDoesFilterPassParams): boolean {
  return this.text.toLowerCase()
    .split(" ")
    .every((filterWord) => {
      return this.customFilter(filterWord, params.node);
    });
}

As you can see the function retrieves all search tokens (separated by spaces) and match every one using the custom filter wich is delegated to the function customFilter(...). Note that the argument node contains the current value of the given row.

The filter function then retrieves the data that will be used in the filter for the current row and tries to match the filter word with any of the tokens.

Note that the key property in each object inside the data array must match the name of the column defined in app.component.ts:

rowData = [
  { name: 'Smith' },
  { name: 'Robert' }
];

Ideally the data array should be provided by some service. In this way you are able to filter for each token in the tokens property. In this case the example will filter for more than one criteria at the same time, for example the input "S 091" will match Smith, you should modify the customFilter function to restrict the filter to only one parameter each time.