Easy select element in Ember.js

Here’s an easy, no-addons select/dropdown in Ember.js, inspired by a blog post by Balint Erdi. There are some great addons for handling selects (like ember-power-select, which is glorious and I use it always), but sometimes you just need to KISS while you’re learning. I know that when I did my first project in Ember, I needed a select element but *any* addon’s documentation would have gone over my head because I was still trying to understand the basics.

In addition to the example below, you can check out this Ember Twiddle, where you can edit and test things yourself. Ember Twiddle is like JSFiddle, Repl.it, and CodePen, but it emulates Ember.

In my-component.hbs:

<select onchange={{action "setSelection" value="target.value"}}>
<option disabled selected> -- Cats or Dogs? -- </option>
<option value="cats">Cats</option>
<option value="dogs">Dogs</option>
</select>
<button {{action 'submit'}}>Submit</button>

In my-component.js:

import Ember from 'ember';
export default Ember.Component.extend({
selectedOption: null,
actions: {
setSelection: function(selected) {
this.set('selectedOption', selected)
console.log(this.get('selectedOption'))
},
submit: function(){
// code to save or sendAction
// e.g. let selectedOption = this.get('selectedOption')
// this.sendAction('submit', selectedOption)
}
}
});

Looks like:

How does this work? Three things happen when a user clicks the dropdown menu and chooses “cat” or “dog”.

First, in the select element, look at value="target.value". What’s happening here is that the value of the select element will become the value of the chosen option, whether it’s a string or an Ember Data record. See how each <option> element has a value too?

Second, thesetSelection action will fire. We use onchange instead of on click, because we want this to fire whenever a user chooses an option the first time or changes their option later… not every time the select is clicked. However, this means that you should have a disabled, default option. Otherwise, if there’s never a change, our action that saves the selection will never fire.

Third, our setSelection action receives the contents of the select’s “target.value” as an argument. That’s because right here {{action "setSelection" value="target.value"}} whatever comes after the name of the action is what’s passed as an argument to the function in our js. And here, our action function receives the argument as "selected” setSelection: function(selected). The value of the argument is the value of whatever option the user chose.

At this point, we’re just going to save their choice to a variable in the component, called selectedOption. The assumption is that the user will probably enter some other things into a form before it ought to all be saved. Then, when the user clicks “Submit”, all we have to do is use this.get('selectedOption') to retrieve the value, and then send the action and the value up to a parent component or route.


Now, what if you want the drop down menu to be filled by records in your Data Store? Like a list of registered organizations, cities, etc? Just throw an each helper in. Don’t forget the # and / in your helpers.

<select required name="organizations" {{action "selectValue" on="change"}}>      
<option disabled selected> -- Choose Organization -- </option>
  {{#each organizations as |organization|}}        
<option value={{organization.id}}>{{organization.name}</option>
{{/each}}

</select>

In older versions of Ember, there was an input helper for selects. But since use cases for selects vary so much, I can see why it may have been removed. Now, selects are a handy way for new Ember devs to learn action handling :P