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.
Feel free to leave comments or questions below.
Want To Learn More?
Try out some more of my Stimulus.js Tutorials.
2 comments on “Stimulus.js Tutorial: How do I filter data in a list or table?”
[…] new feature of Stimulus 2.0 is CSS Classes. In the Todo Filter tutorial, it uses class to hide data. The first thing is to add the class to the […]
Hi there John , thanks for a great article, really helpful. Btw I think you should add `.toLowerCase()` before u do the string matching so that if the filterablekey has any uppercase charater, it would be able to match correctly.
like this
`let filterableKey = el.getAttribute(“data-filter-key”).toLowerCase()`