0

I am trying to build Alphabet base filter in LWC Datatable. I want to filter opportunity name based on the Alphabet pressed by the user i.e if letter 'A' is pressed then I should see only those opportunities where opportunity name starts with letter 'A' .This is where i am not able to find a solution how to filter the datatable based on the action of the user , I want to do this filter in js file as I already have the data which needs to be filtered. if somebody has implemented the same kind of functionality and can share the knowledge that will be helpful.

JS code snippet

handleLetterFilter(event){
    this.allProducts = [...this.products];
    let letter = event.target.text;
    console.log('This is the letter ',letter);
    if(letter != 'ALL'){

    } else {
        console.log('This is the length',this.allProducts.length);
    }
}

HTML code Snippet

 <ul class="slds-list_horizontal slds-has-block-links_space">
    <li><a onclick={handleLetterFilter}>A</a></li>
    <li><a>B</a></li>
    <li><a>C</a></li>
    <li><a>D</a></li>
    <li><a>E</a></li>
    <li><a>F</a></li>
    <li><a>G</a></li>
    <li><a>H</a></li>
    <li><a>I</a></li>
    <li><a>J</a></li>
    <li><a>K</a></li>
    <li><a>L</a></li>
    <li><a>M</a></li>
    <li><a>N</a></li>
    <li><a>O</a></li>
    <li><a>P</a></li>
    <li><a>Q</a></li>
    <li><a>R</a></li>
    <li><a>S</a></li>
    <li><a>T</a></li>
    <li><a>U</a></li>
    <li><a>V</a></li>
    <li><a>W</a></li>
    <li><a>X</a></li>
    <li><a>Z</a></li>
    <li><a onclick={handleLetterFilter}>ALL</a></li>
  </ul>
4
  • What specific problem you are facing, can you add the code here? May 29 '20 at 14:26
  • There is a section of the lightning-datatable documentation about filters that will be helpful (under Creating Header Actions).
    – nbrown
    May 29 '20 at 14:31
  • @nbrown i checked but there is no clear answer May 29 '20 at 14:34
  • 1
    Please read How to Ask and then edit your post to contain a specific, detailed question with the relevant code.
    – David Reed
    May 29 '20 at 14:42
2

You need a separate variable to show the filtered results. I wrote a complete example in this playground.


<template>
    <lightning-card title="Filters">
        <div class="slds-align_absolute-center">
    <template for:each={alphabet} for:item="letter">
        &nbsp;<a onclick={handleFilterChange} key={letter} data-filter={letter}>
            {letter}
        </a>
        &nbsp;|
    </template>
    <a onclick={handleFilterChange} data-filter="">
        ALL
    </a>
        </div>
    <lightning-datatable 
        columns={columns}
        data={currentPage}
        key-field="index">
    </lightning-datatable>
    <div class="slds-align_absolute-center">
    <lightning-button-group>
    <lightning-button label="First" onclick={firstPage}>
    </lightning-button>
    <lightning-button label="Previous" onclick={previousPage}>
    </lightning-button>
    <div class="slds-m-horizontal_medium slds-align_absolute-center">
    {pageNumber} of {maxPageNumber}
    </div>
    <lightning-button label="Next" onclick={nextPage}>
    </lightning-button>
    <lightning-button label="Last" onclick={lastPage}>
    </lightning-button>
    </lightning-button-group>
    </div>
    </lightning-card>
</template>

import { LightningElement } from "lwc";

const NAMES = [
  "Noah", ...
   // Top 2k baby names of 2016 //
];

export default class App extends LightningElement {
  filteredResults = [];
  currentLetter;
  pageNumber = 1;
  pageSize = 10;
  columns = [
      { fieldName: 'name', label: 'Name', type: 'text' }
  ];
  alphabet;
  connectedCallback() {
      this.alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
      this.handleFilterChange();
  }
  nextPage() {
    this.pageNumber = Math.min(
      this.pageNumber + 1,
      this.maxPageNumber
    );
  }
  previousPage() {
    this.pageNumber = Math.max(1, this.pageNumber - 1);
  }
  firstPage() {
    this.pageNumber = 1;
  }
  lastPage() {
    this.pageNumber = this.maxPageNumber;
  }
  get maxPageNumber() {
    return Math.floor(
      (this.filteredResults.length + (this.pageSize - 1)) / this.pageSize
    );
  }
  get currentPage() {
    return this.filteredResults.slice(
      (this.pageNumber - 1) * this.pageSize,
      this.pageNumber * this.pageSize
    ).map((name,index)=>({ key: index, name }));
  }
  handleFilterChange(event) {
    if(event) {
        this.currentLetter = event.target.dataset.filter;
    }
    if (this.currentLetter) {
      this.filteredResults = NAMES.filter((name) =>
        name.startsWith(this.currentLetter)
      );
    } else {
      this.filteredResults = [...NAMES];
    }
    this.filteredResults.sort((a,b)=>a<b?-1:1);
    this.pageNumber = 1;
  }
}
1
  • thanks a lot i will try to implement the same May 29 '20 at 20:52
1

First, I want to dissect this statement:

I already have the data which needs to be filtered

Salesforce typically places limits on how much data you can query for and store. You either don't have all the data, or are very likely to reach limits related issues and slow performance. You should never query for the full data set all at once.

Next to the answer to your question.

The way I would approach this is to create a set of methods that can easily build a query dynamically. Then, to filter all you would do is add your letter to a like clause at the end of the query: WHERE Name LIKE \'' + filterLetter '%\'';

This is an approach I used a while back in visualforce components. Disclaimer: If I had the time I would love to rewrite this and possibly provide an LWC version. It does not follow best practices but it will illistrate the point.

This example does take advantage of the standard set controller. It will only query for the first "page" of records. When you click to the next page you will have to query for more records. There's a few ways to achieve this either manually or taking advantage of the custom set controller and storing necessary information about the set controller's state in a json object on the JS side to pass back to the controller in each call.

1
  • Thanks for your input yes i am filtering the data from apex May 29 '20 at 20:56
0

As @gNerb said to avoid performance issues, your data should not exceed a certain limit.

You can see the example below on this Playground

   <lightning-input type="search" label="Search" onchange={handleSearchPhone}>
    </lightning-input>
    <lightning-datatable data={phones} columns={columns} key-field="id">
    </lightning-datatable>
export default class App extends LightningElement {
    _phones = [

        { id: '1', name: 'Nokia Lumia' },
        { id: '2', name: 'Samsung Galaxy Note' },
        { id: '3', name: 'Iphone 25' },
        { id: '4', name: 'Nokia 3310' },
        { id: '5', name: 'Samsung Galaxy S50' },
     ];
    phones = [];
    columns = [
        { label: 'Available phones', fieldName: 'name' }
    ];
    connectedCallback() {
        this.phones = [...this._phones];
    }
    handleSearchPhone(event) {
        const inputValue = event.target.value[0];
        console.log('inputValue', inputValue);

        const regex = new RegExp(`^${inputValue}`, 'i');     
        this.phones = this._phones.filter(row => regex.test(row.name));

        if (!event.target.value) {
            this.phones = [...this._phones];
        }
    }
}

1
  • thanks i will try the above approach May 29 '20 at 20:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.