Proof of Concept - Dynamically Filtering a Large Select

Proof of Concept - Dynamically Filtering a Large Select

A while back a friend wrote me with an interesting problem. He has a form where one of the fields can have near a thousand or so entries. It didn't impact load time that much for his users, but it did create a dropdown control that was difficult to use. He was curious to see if there was a way to let the user filter the dropdown to make it a bit more easier to read. Here's what I came up.

First, I did not go down the datalist route. While that provides similar behavior, it only lets you pick a string value. A select field lets you display a string value while binding it to a value in the option. So for example, the text displayed to the user could be American and the value some primary key value used in a database.

Instead of using a datalist, I went with a simple text field next to the dropdown:

<input type="search" id="filter" placeholder="Filter" autocomplete="off">
<select id="myOptions"></select>

My JavaScript code then listened for changes to the filter and applied them to a filter on the data that populated the dropdown. Here's the complete code.

function getOptions() {
	let result = [];
	let prefix = ["A","B","C","D","E","F","G","H","I","J","K"];
	prefix.forEach(p => {
		for(let x=0; x<250; x++) {
			result.push(p+x);
		}
	});
	return result;
}


function setOptions(opts) {
	let select = document.querySelector('#myOptions');
	
	//set values for drop down
	let html = '';
	opts.forEach(o => {
		html += `<option>${o}</option>`;
	});
	select.innerHTML = html;
}

let filter = document.querySelector('#filter');

filter.addEventListener('input', () => {
	let value = filter.value.trim().toLowerCase();
	let options = (getOptions()).filter(f => {
		return value === '' || f.toLowerCase().includes(value);
	});
	setOptions(options);
},false);

setOptions(getOptions());

So first off, getOptions is meant to represent the API call or some other 'real' process. In my case I'm just generating dummy data.

The function setOptions handles setting the options available to the dropdown. It expects an array of values passed to it. By default this is the full result of getOptions, but when you type into the filter, it filters the values returned. Here's a demo:

See the Pen Select Filter by Raymond Camden (@cfjedimaster) on CodePen.

I shared this on Twitter and got some good responses. Markus Oberlehner responded with a fork of the CodePen where he does something fascinating. Clicking in the filter field activates the multiple property of the dropdown, providing a bit more visual feedback of the filter being performed. Here's his version.

See the Pen Select Filter by Markus Oberlehner (@maoberlehner) on CodePen.

Let me know what you think - remember you can fork my CodePen (or Markus) to work on your own version!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com