In a form, in a table, I have...
<tr><td>Score (-10 to +10):</td><td>{{input type="range" min="-10" max="10" steps="1" value=game.score }}<br/>Score: {{game.score}}</td></tr>
This almost works; the correct value is reported below the slider, and any value set using the slider is stored correctly. But the slider is not initialized with the value correctly
. If I replace the binding name with a constant (e.g. "7"), that does initialize properly.
This looks like an Ember bug, in that this same format works for other input types and it does report it correctly; it's just the initialization that's wrong. But it seems kind-of big to be wrong, so there must be some secret magical incantation experienced users know, that I'm just ignorant of. How do I get this to initialize?
The best way to handle a range slider in Ember is to use the native HTML implementation instead of the input helper. The input helper is only for text and checkboxes.
Option 1: handling the slider change with the mut helper:
<input type="range"
oninput={{action (mut game.score) value="target.value"}}
min={{min}}
max={{max}}
value={{game.score}}
steps="1">
In this example, as a slider gets moved, oninput fires. (onchange would fire only after the user releases the mouse). Then, the mut helper changes the value of game.score
to be the value of the slider. target.value
is normal HTML stuff, where target is the input dom element itself.
Option 2: use Ember's built-in event handlers
<input type="range"
min={{min}}
max={{max}}
value={{game.score}}
steps="1">
In your component js, add the input function:
import Ember from 'ember';
export default Ember.Component.extend({
input(event) {
console.log(event.target.value)
}
});
Here, event.target.value
contains the value of the slider. The use of event listeners (instead of explicit actions) is a little uncommon, so if this surprises you, read the links at the bottom. Now that you have the value, you can call actions within the component, set some things, or send it up to a controller, etc.
Option 3: use a closure action
Closure actions (actions that are set equal to event names in the template) receive the event as a default argument.
<input type="range"
oninput={{action 'sliderMoved'}}
min={{min}}
max={{max}}
value={{game.score}}
steps="1">
In the component:
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
sliderMoved(e) {
console.log(e.target.value)
// do something with the value
}
}
});
Document these secret magical incantations well in your codebase. None are obvious at first glance.
It is very helpful to read the MDN docs on range inputs, the Ember docs for the mut helper, and Ember's supported event names.