My WebDev Notes: Filter table
Tags: html, css, javascript
Published: 2020-04-01 10:33:44

---
title: My WebDev Notes: Filter table
published: true
description: A detailed experiment on how to create a filter table with JavaScript
tags: html, css, javascript
series: My WebDev Notes
---

> <b>Check the filter table online: https://ziizium.github.io/my-webdev-notes/filtertable/</b>

Tables contain data and you might find yourself in a situation where the data on a single is quite much even if you employ pagination.

Web applications like [phpMyAdmin](https://www.phpmyadmin.net/) employ a particular feature of filtering database names as you type without the need for a page refresh.

![An image of phpmyadmin web application showing database names in their unfiltered form](https://dev-to-uploads.s3.amazonaws.com/i/z6h1ga1q7226lwqyj2ih.png)<figcaption>Unfiltered database names in phpMyAdmin</figcaption>

![An image of phpmyadmin web application showing database names in their filtered form](https://dev-to-uploads.s3.amazonaws.com/i/xd3xlfisqper9ukugxmx.png)<figcaption>Filtered database names in phpMyAdmin</figcaption>

This experiment is about recreating that feature using HTML, CSS, and JavaScript.

<hr>

The HTML will have a _form_ which in turn will contain a single _form input_ and the table that's going to be filtered.

```html
<main>
    <h1>Programming languages</h1>

    <form>
        <label for="searchInput">Enter search term: </label>
        <input type="text" id="searchInput" class="searchInput" placeholder="Search by Language" title="Type a Programming Language">
    </form>

    <table class="table" id="table">
	 <tbody>
	 <thead>
	    <tr class="header">
	        <th>Programming Language</th>
	        <th>Inventor</th>
	    </tr>
	 </thead>

	 <tr>
		<td>JavaScript</td>
		<td>Brendan Eich</td>
	 </tr>

	 <tr>
		<td>Python</td>
		<td>Guido van Rossum</td>
	 </tr>

	 <tr>
		<td>C</td>
		<td>Dennis Ritchie</td>
	 </tr>

	  <tr>
		<td>PHP: Hypertext Preprocessor</td>
		<td>Rasmus Lerdorf</td>
	  </tr>
         
         <!-- You can search online for other programming languages and their creator -->
         </tbody>
    </table>
```

The following CSS snippet is for _cosmetics_:

```css
/**
  * CSS for cosmetics
  */
h1 {
	text-align: center;
}

label {
    font-size: 1.5em;
    margin-bottom: 0.7em;
}

form {
    margin-bottom: 1em;
}

th,
td {
    text-align: left;
    padding: 0.75em;
}

tr {
    border-bottom: 1px solid #ddd;
}

tr.header,
tr:hover {
    background-color: #f1f1f1;
}

.header th:nth-child(1) {
    width: 60%;
}

.header th:nth-child(2) {
    width: 40%;
}

.searchInput {
    width: 60%;
    font-size: 1em;
    padding: 0.6em;
    border: 1px solid #dddddd;
    margin-bottom: 0.75em;
}

.table {
    border-collapse: collapse;
    width: 100%;
    border: 1px solid #dddddd;
    font-size: 1.2em;
}
```

JavaScript is the core part of the application that's going to make the filtering possible. Therefore, I am not writing it all at once rather we'll dissect it together to figure out _why_ and _how_ it works.

When you take a look at the HTML _form input_ you will realize an _HTML ID_ is attached to it. Here it is once again:

```html
<!-- I have omitted other attributes of the input to keep things short -->

<input type="text" id="searchInput">
```

Text entered into this _form input_ will be used as the _filter_. We'll have to observe changes when a user types in this _input_ and compare it against the data in the table. The best way to do this is to attach an _event listener_.

In JavaScript, we make use of the <code>addEventListener</code> method to attach an event to an HTML element. It accepts parameters like:

* An HTML DOM Event
* A _function_
* A boolean value indicating whether to use event bubbling or event capturing

The particular _event_ we'll have to watch out for is the <code>keyup</code> _event_ because we'll have to make comparisons with the table when the user types.

The _function_ (defined later) describes what happens when the user types.

We'll pass a <code>false</code> value as the third parameter to this function which means the _event listener_ will use _event bubbling_

```js
// get the form input
let searchInput = document.getElementById('searchInput');

// attach an event listener
searchInput.addEventListener("keyup", filterTable, false);
```
Next we need to define the function <code>filterTable</code>. We'll start by doing the following:

* Get the user input
* Select the table
* Select all table rows in the selected table

```js
function filterTable() {
    // get the user input
    let filter = searchInput.value.toUpperCase();

    // grab the table
    let table = document.getElementById("table");

    // get all table rows in the selected table
    let tr = table.getElementsByTagName("tr");
}
```

The <code>getElementsByTagName()</code> used in selecting the <code>tr</code> returns an <code>HTMLCollection</code>, if we are to make any comparison we'll have to loop through the collection.

Before that, __we should know that the user will filter the table using the name of the programming language__ which is inside the first table data (<code>td</code>) of each row.

Therefore, when we perform the loop we'll have to select every first table data in each row:

```js
function filterTable() {
    // previous code remain the same
    
    for (let i= 0; i < tr.length; i++) {

        // select every first table data in each row
        let td = tr[i].getElementsByTagName("td")[0];
        
        // more to follow

    }
}
```

Now that we have the _table data_, we are ready to make a comparison. We check if the user input exists in the table row using the <code>indexOf</code> operator. If it exists we show the user and hide the remaining data in the table. A simple <code>if/else</code> will do the trick:

```js
function filterTable() {
    // previous code remain the same
    
    for (let i= 0; i < tr.length; i++) {

        // previous code remain the same

        if (td) {
            if (td.innerHTML.toUpperCase().indexOf(filter) > -1) { // we found a match

                tr[i].style.display = "";

	        } else { // no match found

                tr[i].style.display = "none";

	        } // end of if(td.innerHTML...)

	    } // end of if(td)

    } // end of for loop 

} // end of function filterTable()
```

Here is the whole function:

```js
function filterTable() {

	// get the user input
	let filter = searchInput.value.toUpperCase();

	// grab the table
	let table = document.getElementById("table");

	// get all table rows in the selected table
	let tr = table.getElementsByTagName("tr");

	for (let i= 0; i < tr.length; i++) {

		// get the first table data of each row
		let td = tr[i].getElementsByTagName("td")[0];

		if (td) { // we got a data to work with

			if (td.innerHTML.toUpperCase().indexOf(filter) > -1) { // we found a match

				// we show it
				tr[i].style.display = "";

			} else { // no match found

				// we hide the table data
				tr[i].style.display = "none";

			} // end of if (td.innerHTML..)

		} // end of if (td)

	} // end of for()

} // end of function filterTable()
```

And the Github repo:

{% github  ziizium/my-webdev-notes %}

_Have fun!_