2

The Ember guide on binding data attributes says that "If you use data binding with a Boolean value, it will add or remove the specified attribute." I'm trying to use this feature to dynamically set the selected attributes on <option>s. I'm finding that I can dynamically set the disabled attribute, but the selected attribute is always omitted, no whether the boolean is true or false.

Given this handlebars template:

<option disabled={{false}} selected={{false}}>One</option>
<option disabled={{true}} selected={{true}}>Two</option>

I get the following HTML:

<option>One</option>
<option disabled>Two</option>

Why doesn't selected={{true}} produce a selected attribute in the rendered output?


To give a bit more context, I'm following this article on How to do a select in Ember 2.0. Using the method described in that article, I can successfully update the data in the controller when the select onchange event fires, but the DOM doesn't update to reflect the change.

I've put together this ember-twiddle, which includes two select elements. One uses select={{bool}}, which doesn't work the way I want it to. The other uses a long-hand {{#if bool}}...{{else}}...{{/if}}, which does work but looks terrible.

nelstrom
  • 18,802
  • 13
  • 54
  • 70
  • 2
    `selected` is a property, not an attribute with a value – Sonny Jan 24 '17 at 22:06
  • Is the problem that you're hardcoding `{{true}}` and `{{false}}`? Your example is a little contrived. Instead of hardcoding `{{true}}` and `{{false}}`, you can hardcode the absence or presence of the `selected` attribute. – Chris Peters Jan 24 '17 at 22:14
  • @ChrisPeters I admit that using `{{true}}` and `{{false}}` looks contrived, but I wanted to keep the example simple. The results would be the same if the `{{}}` referenced a computed property which returned `true` or `false`. – nelstrom Jan 24 '17 at 22:28
  • A thought: maybe a `disabled` option cannot also be `selected`? – Chris Peters Jan 25 '17 at 03:02

3 Answers3

4

Thanks to everyone who took the time to post an answer my question. Sonny's comment pointed me in the right direction:

selected is a property, not an attribute with a value

This was news to me and it sent me down a rabbit-hole of discovery. I found this SO answer to be especially helpful.

When I posted the question, I didn't appreciate the difference between attributes and properties. I was expecting to see the selected attribute appear in the DOM, but this doesn't happen. I now understand that the selected property is being correctly set, and the fact that the <option> tag doesn't appear in the DOM with a selected attribute is of no consequence.

This code snippet helps to illustrate why I was confused. Both of the resulting <select> dropdown menus appear the same, with option 2 initially selected. The selected attribute does not appear in the DOM when it's set using selected={{true}}, but it does appear in the DOM in the other case:

<select>
  <option>1</option>
  <option selected={{true}}>2</option>
</select>

<select>
  <option>1</option>
  <option selected>2</option>
</select>

Here's the same snippet as a Twiddle

Community
  • 1
  • 1
nelstrom
  • 18,802
  • 13
  • 54
  • 70
1

You can use a helper which compares you option value to a reference somewhere like

<select onchange={{action "countryChanged" value="target.value"}}>
{{#each countries as |country|}}
    <option value={{country.id}} selected={{is-equal country model.address.country_code}}>{{country.name}}</option>
{{/each}}
</select>

Inside your "Helpers" folder (create if not already there)

create your helper file like "is-equal.js"

import Ember from 'ember';

export default Ember.Helper.helper(function([lhs, rhs]) {
  return lhs === rhs;
});

Which will just compare 2 values and return a boolean, you could also return a classname or whatever you like.

The action sets the user selected value to the model.address.country_code, the helper compares the new values, if the selected value matches the option value selected will get set to true.

0

I was able to set the selected option using a variable as seen here: https://gist.github.com/fenichelar/d3cfa5c59783fdbf02d32bcc3b3a028d

Here is the Ember Twiddle: https://ember-twiddle.com/d3cfa5c59783fdbf02d32bcc3b3a028d?openFiles=templates.application.hbs%2C

Relevant Code:

application.js

import Ember from 'ember';

export default Ember.Controller.extend({
  one: false,
  two: true,
  three: false
});

application.hbs

<div>
  <select>
    <option selected={{one}}>One</option>
    <option selected={{two}}>Two</option>
    <option selected={{three}}>Three</option>
  </select>
</div>
Alec Fenichel
  • 1,257
  • 1
  • 13
  • 27