Bitwise Breakdown

Multi-select Picklist in Salesforce LWC: Accessability and Advance Functionality

Published on 3 min read
Multi-select Picklist Salesforce LWC

In the previous post, we walked through the core functionality of our Multiselect Picklist Lightning Web Component (LWC). Now, it’s time to dive deeper into advanced features such as performance optimizations, and accessibility enhancements. These tweaks will take our component from functional to production-ready.

You can follow along with the full code from the Salesforce Custom Components.


Improve Component Performance

Performance is crucial, especially when dealing with large datasets or complex UI elements. Let’s look at how to optimize our component for better performance.

Debounce Input Events

The handleInputKeyUp method triggers every time a user types a character. For better performance, we’ll introduce a debounce mechanism to limit how frequently the search logic runs. This reduces the number of filter operations, especially when the user types quickly.

handleInputKeyUp(event) {
  const searchTerm = event.target.value.toLowerCase();
  clearTimeout(this.debounceTimeout);
 
  this.debounceTimeout = setTimeout(() => {
    this.options = this.emptyOptions
      .filter((option) => option.value.toLowerCase().includes(searchTerm))
      .map((option) => ({
        ...option,
        ariaLabel: option.label + ' ' + option.checked,
        checked: this.values.includes(option.value),
      }));
  }, 300); // 300ms debounce time
}

Explanation:

  • clearTimeout ensures that the previous timeout is cleared if the user is still typing.
  • We use a 300ms delay to debounce the input event, preventing the method from being called excessively as the user types.

Enhance Accessibility

Building accessible components ensures that everyone, including users with disabilities, can interact with your application. Salesforce provides some built-in accessibility features, but we can further enhance it.

Aria Attributes

We are already using aria-label in the checkboxes for each option. Let’s ensure that the input and the dropdown elements are also accessible by adding additional aria attributes:

<input
  type="text"
  class="slds-input search-input"
  aria-expanded={showDropdown}
  aria-controls="multiselect-dropdown"
  aria-haspopup="listbox"
  placeholder={placeholder}
  onkeyup={handleInputKeyUp}
/>

Explanation:

  • aria-expanded: Indicates whether the dropdown is open or closed.
  • aria-controls: Links the input with the dropdown list.
  • aria-haspopup: Indicates that the input will trigger a listbox.

Keyboard Navigation

To improve usability, let’s allow users to navigate through the dropdown using the keyboard.

focusedIndex = -1;
handleInputKeyUp(event) {
  switch (event.keyCode) {
    case 40: // Arrow down
      this.focusNextItem();
      break;
    case 38: // Arrow up
      this.focusPreviousItem();
	  break;
    case 13: // Enter key
      this.selectFocusedItem();
      break;
    case 27: // Esc key
      this.showDropdown = false;
      break;
  }
}
 
focusNextItem() {
  if (this.options.length > 0) {
	this.focusedIndex = (this.focusedIndex + 1) % this.options.length;
	this.updateFocus();
  }
}
 
focusPreviousItem() {
  if (this.options.length > 0) {
    this.focusedIndex = this.focusedIndex === 0 ? this.options.length - 1 : this.focusedIndex - 1;
    this.updateFocus();
  }
}
 
updateFocus() {
  this.template.querySelectorAll('.dropdown-container__list-item').forEach((item, index) => {
    if (index === this.focusedIndex) {
      item.classList.add('focused-item');
      item.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
    } else {
      item.classList.remove('focused-item');
    }
  });
}
 
selectFocusedItem() {
  if (this.focusedIndex !== -1 && this.options.length > 0) {
    const value = this.options[this.focusedIndex].value;
    this.selectPicklistValue(value);
  }
}

Below is the css to highlight the focused item

.focused-item {
  background-color: #f0f8ff;
  outline: none;
}

Explanation: This logic allows users to navigate through options using the arrow keys, select an option with the Enter key and close the dropdown using Esc key. focusedIndex keeps track of the currently focused list item. updateFocus() visually updates the focused item, adding a focused-item CSS class.


Conclusion

In this post, we covered the advanced features of the Multiselect Picklist component, including:

  • Performance optimizations with debounce.
  • Accessibility improvements through ARIA attributes and keyboard navigation.

You can implement these features in your own project or try out the full solution from the Salesforce Custom Components.