Stimulus MultiSelect
Tags: javascript, multiselect, webdev, stiumulus
Published: 2022-11-22 15:54:39

## The problem

Every developer had to struggle with choosing the right plugin/package for things that are time consuming or have already been done in ways that suit their needs. Juggling 🤹‍♂️ between a package that is smaller in size or has certain features that we need can be frustrating.

![Options](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdxikye15f8pnsz4lbgt.gif)

But what happens when there are no packages to choose from? On top of that, what if there is a feature that millions of developers need, but struggle to find answers or make custom solutions for every app they make.

I am, of course, talking about the atrocious implementation of the multiple select feature built into every major browser 😫

![Built-in multiple select](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qc0t2qp53kjn9hasseni.png) 

![Crash](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txxfq5ulbs09ce8rpgze.gif)

## The solution

Since this frustrated my colleagues and me for a long time we decided to [make our own implementation and open source](https://github.com/WizardComputer/stimulus-multiselect) it.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t992xuq7sf3u4he76np4.gif)

We are not pioneers in this, naturally. There is many a plugin trying to solve the same problem. But what stuck with me when researching is none of them seem to quite scratch the perfectionist itch (now always a good thing 😅). Some of them require big dependencies like vue.js or jQuery, while some of them just lack the features or the ability to be customized.

# Stimulus Multiselect

You are going to **need** [stimulus.js](https://stimulus.hotwired.dev/) as a dependency for this package to work. It is a minimal, easy to understand javascript flavor for handling HTML.

If you are using a js bundler with `node_modules` support (such as esbuild, rollup.js or Webpack) install the package from npm:

```plain
yarn add @wizardhealth/stimulus-multiselect
```

If you're using [importmap-rails](https://github.com/rails/importmap-rails), you'll need to pin `@wizardhealth/stimulus-multiselect`:

```plain
./bin/importmap pin @wizardhealth/stimulus-multiselect
```

## Usage

Load your stimulus application as usual and the register the multiselect
controller with it:

```javascript
import { Application } from '@hotwired/stimulus'
import { Multiselect } from '@wizardhealth/stimulus-multiselect'

const application = Application.start()
application.register('multiselect', Multiselect)
```

The multiselect has many modes of working. You can fetch data remotely or load a static json collection of items. An example of this static approach:

```html
<div data-controller="multiselect" data-multiselect-items-value='[{ "value": "cuckoo", "text": "Cuckoo 🐦"}, { "value": "macaw", "text": "Macaw 🦜"}, { "value": "rooster", "text": "Rooster 🐓"}]' data-placeholder="Search for birds...">
  <select multiple="multiple" class="multiselect__hidden" data-multiselect-target="hidden" name="form[test_ids][]" id="form_test_ids"></select>
</div>
```

# Let's build an app

We are gonna build a Rails app (since Stimulus is mostly used with Rails) that has a backend of different sports. We are gonna search through these sports with the help of the multiselect and return the results back to show in the dropdown.

## The setup

1. Create a new app `rails new multiselect_test`
2. Scaffold Sports so we can search through them `rails g scaffold Sport name:string`
3. Migrate it! `rails db:migrate`
4. Start up the server `rails s` and get to creating some sports
![Creating sport](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ag17bfv5fa7b0hrv57fb.gif)

5. Add the package `yarn add @wizardhealth/stimulus-multiselect`

## The implementation

We are going to use the sports#index page for testing. So we need to make the following changes to the controller and view.

- We are going to make use of a simple where for the purposes of this example. The index needs to like like this. The parameter that contains the search term from the select input is inside `params[:q]`
```ruby
# app/controllers/sports_controller.rb

def index
  @sports = Sport.where("name LIKE ?", "%#{params[:q]}%")

  respond_to do |format|
    format.json
    format.html
  end
end
```
- The response that the select needs is JSON. So let's change the json response views that are inside `app/views/sports/`
```ruby
# app/views/sports/index.json.jbuilder

json.array! @sports, partial: "sports/sport", as: :sport
```

The select needs a json that contains the **value** (usually the id) and the **text** value (what is shown when selecting)
```ruby
# app/views/sports/_sport.json.jbuilder

json.value sport.id
json.text sport.name
```

- Lastly, we need to put the select HTML somewhere. Let's use the `sports/index.html.erb` for this
```html
<!-- app/views/sports/index.html.erb -->

<div data-controller="multiselect" data-multiselect-search-url-value="/sports" data-placeholder="Search for sports...">
  <select multiple="multiple" class="multiselect__hidden" data-multiselect-target="hidden" name="sports[]" id="sport_ids"></select>
</div
```
- Add the contents of [this file](https://github.com/WizardComputer/stimulus-multiselect/blob/main/src/multiselect.css) to your css

```css
/* app/assets/stylesheets/application.css */

// The css contents from the file mention above go HERE
```

- When going to _localhost:3000/sports_ we should see this

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r9yl1xeuq2d22zsulgqo.png)

## The end product

Now just search any sport you like:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dav6el74k9f6mlnear52.gif)



## Why Stimulus Multiselect ❓

1. Easy to set up
2. Lightweight
3. [Good documentation](https://github.com/WizardComputer/stimulus-multiselect#stimulus-multiselect-controller)
4. Lot of options for loading data and handling selected items
5. Design is customizable (css file is extracted so you can make the select suit your application look)
6. Accessible
7. Contributions and issue raising are welcome on [our GitHub page](https://github.com/WizardComputer/stimulus-multiselect)

## The finish line 🔚

Would love to know what you think. Comment, review the code, try the select and tell us how we can improve 💚

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j94cak3brw93gvmvajn3.gif)