DEV Community

Cover image for Rails + Stimulus.js sorting filter on select
marelons1337
marelons1337

Posted on • Originally published at blog.rafaljaroszewicz.com

Rails + Stimulus.js sorting filter on select

In my new project I wanted to introduce sorting on the index page for my records and I came up with this simple Stimulus.js solution.

First, I created the select

<select aria-label="select">
  <option value="id desc">Latest</option>
  <option value="id asc">Oldest</option>
  <option value="name asc">A-Z</option>
  <option value="name desc">Z-A</option>
</select>
Enter fullscreen mode Exit fullscreen mode

Then once i have my element in place I can create a Stimulus controller

rails g stimulus select

And also attach it to my select

<select data-controller="select" aria-label="select">
  <!-- content -->
</select>
Enter fullscreen mode Exit fullscreen mode

Now, let's attach the action to our element that is responsible for selecting.

export default class extends Controller {
  params = new URLSearchParams(window.location.search)
  connect() {
    // attach action to the element
    this.element.dataset.action = "change->select#filter"
    // set initial params after page load
    this.element.value = this.params.get('sort')
  }
  filter() {
    const query = this.element.value
    this.params.set('sort', query)
    window.location.search = this.params.toString()
  }
}
Enter fullscreen mode Exit fullscreen mode

The reason I'm setting this.element.value in my connect() method is because of the next method introduced, filter(). Here I will set the search location of the window object to the params we got from our select. However this will refresh the page and cause the select to reset.

Last step is adding the actual filtering to the controller, but to make sure that it's safe and user cannot send their own values I also introduce an array of values available in this filter.

class Property::SalesController < ApplicationController
  before_action :set_property_sale, only: %i[ show edit update destroy ]
  SORT_METHODS = ['id asc', 'id desc', 'name asc', 'name desc']

  # GET /property/sales or /property/sales.json
  def index
    @property_sales = Property::Sale.all
    @property_sales = @property_sales.order(params[:sort]) if params[:sort].presence.in? SORT_METHODS
  end
end
Enter fullscreen mode Exit fullscreen mode

Now our input is safe because only these 4 strings can trigger a database call.

Top comments (0)