Octane and <select>

Whenever I am in need of a select element, I find myself doing this:

  <select local-class="select" onchange={{this.setInterval}} {{did-insert this.updateInterval}} {{did-update this.updateInterval @interval}}>
    <option selected={{eq this.interval "1"}} value="1">1 minute</option>
    <option selected={{eq this.interval "60"}} value="60">1 hour</option>
    <option selected={{eq this.interval "120"}} value="120">2 hours</option>
    <option selected={{eq this.interval "240"}} value="240">4 hours</option>
    <option selected={{eq this.interval "720"}} value="720">12 hours</option>
    <option selected={{eq this.interval "1440"}} value="1440">24 hours</option>
  </select>

I am wondering, if there is a good way to remove all that boilerplate and generate an component which behaves more like this:

<EmberSelect>
  <Entry @val="1" @text"1 minute"/>
  <Entry @val="60" @text"1 hour"/>
</EmberSelect>

I don’t necessarily want to make it exactly look like that, but I want to find a way which lets me remove all the boilerplate code. Pretty much my issues is that I need a way which lets me define the available elements within the block. Any ideas?

(I am aware of power-select, but it’s just too heavy for our needs)

Yeah I know what you mean RE power select. I’ve used emberx-select in the past but with Octane it’s super easy to write a little select component like what you’re describing. This is a very basic one I wrote recently:

// app/components/u-i/select.hbs
<select
  class="..."
  ...attributes
  {{on "change" (pick "target.value" @onChange)}}
>
  {{yield (hash option=(component "u-i/select/option" currentValue=@value))}}
</select>

and the option component:

// app/components/u-i/select/option.hbs
<option value={{@value}} selected={{if (eq @currentValue @value) true false}}>{{@label}}</option>

And it would be invoked like this…

<UI::Select @onChange={{action (mut this.someProp)}} @value={{this.someProp}} as |s|>
  <s.option @label="option 1" @value="option1" />
  <s.option @label="option 2" @value="option2" />
</UI::Select>

Note that the select component uses the pick helper from ember-composable-helpers in order to avoid creating a backing js class with the action. So it would either require using ember composable helpers or defining a js class for the select component with the action handler.

2 Likes

Thanks a lot . That’s exactly what I was looking for. I think I still need some time to get comfortable with that pattern, though.

Hey @Hummingbird, <select> elements have always seemed a bit strange in Ember. I’ve been using Zestia’s native select box for years. Rather than author your own, consider using their addon?

Thank you. But this can be done too easily without adding an addon.