Skip to content →

Stimulus.js Tutorial: How do I filter data in a list or table?

Let’s work off the previous Todo tutorial and add a way to filter those Todos using just Stimulus.

We will only need to work on the todos/index.html file, and to add one Javascript controller. This example will highlight how Stimulus enhances your server rendered HTML, without the need to build complicated constellations of Javascript objects.

Let’s begin by adding a div that will wrap our table, and a text input that we will use as a the filter source. The wrapper div will hold the filter controller. The input will call the filter#filter method on the controller, and it will supply the filter value from the target filter.source that we’ll use to hide our rows. Each of the tr elements is set as a filter.filterable target, and then we’ll set the value that we should filter at data-filter-key; in our case, the todo status and the title, all in lower case.

<div data-controller="filter">
  <input data-target="filter.source" 
              data-action="input->filter#filter" 
              type="text" 
              class="filter" 
              placeholder="Filter Todos" />
  <table>
    <% @todos.each do |todo| %>
      <tr data-target="filter.filterable" 
            data-filter-key='<%= "#{todo.completed ? 'done' : 'todo' } #{todo.title}".downcase %>'>
        <td>
           <input type="checkbox" <% if todo.completed %> checked <% end %> >
           <%= todo.title %>
        </td>
      </tr>
    <% end %>
  </table>
</div>

That’s all the html we need to update. Let’s move on to the javascript controller. Name your file filter_controller.js and setup the Stimulus controller template:

import { Controller } from "stimulus"

export default class extends Controller {

  }
} 

Let’s add the targets list, one for the input field source, and one for all the filterable rows:

  static targets = [ "source", "filterable" ]

And finally, let’s add the filter method:

  filter(event) {
    let lowerCaseFilterTerm = this.sourceTarget.value.toLowerCase()

    this.filterableTargets.forEach((el, i) => {
      let filterableKey =  el.getAttribute("data-filter-key")

      el.classList.toggle("filter--notFound", !filterableKey.includes( lowerCaseFilterTerm ) )
    })

The filter method will first pull the filter term from the source target, our input field on the index.html page. Then it will go through each of the filterableTargets, element by element, get the filter key that we set on each element, and toggle a class that will hide elements that don’t have the filter term in the filter key.

The CSS class that hides is element is here:

.filter--notFound {
  display: none;
}

Now you have a simple way to filter data on your page.

Comments or Questions? Find me on twitter @jpbeatty

Want To Learn More?

Try out some more of my Stimulus.js Tutorials.

Excited for Stimulus?

Drop your email below, and you won’t miss the next Stimulus Tutorial


Published in ruby on rails Stimulus JS

Comments are closed.