5

I want to use a slider control to input a selection. The possible values are: 5000, 25000, 50000, 75000, and 100000. However, I cannot get the range input to limit to those choices. The closest thing I've got is this:

<datalist id="valid-options">
  <option>5000</option>
  <option>25000</option>
  <option>50000</option>
  <option>75000</option>
  <option>100000</option>
</datalist>
<input type="range" min="5000" max="100000" step="5000" list="valid-options" ng-model="selectedValue" />

You can see the full sample here: http://jsfiddle.net/au14Lv2t/1/

The problem with this solution is that it allows for invalid values like 10000, 15000, etc.

I'm looking for an AngularJS (or pure HTML5/JS/CSS) solution. I would prefer not to introduce jQuery.

Thanks!

4
  • why not use a select instead? Commented Oct 29, 2014 at 21:59
  • Looks like you will have to use custom type range emulation. Commented Oct 29, 2014 at 22:12
  • @serakfalcon the UI design calls for a slider control. That's definitely the fallback position, though. Commented Oct 29, 2014 at 22:18
  • @dfsq Can you elaborate? Commented Oct 29, 2014 at 22:18

3 Answers 3

2

you can search for the closest valid value and set the input value to that value for each value change event

var inputElement = document.getElementById('customRangeInput');

inputElement.oninput = setInput;
inputElement.onchange = setInput;   // IE fix

function setInput(){
    inputElement.value = closestValue(inputElement.value);
}

var validValues = [5000,25000,50000,75000,100000];
function closestValue(input)
{
    var differences = [];
    for (var i = 0; i < validValues.length; i++)    
        differences.push( Math.abs(validValues[i] - input));

    var index = indexOfSmallest(differences);
    return validValues[index];      
}

function indexOfSmallest(inputArray) {
    var lowest = 0;
    for (var i = 1; i < inputArray.length; i++) {
        if (inputArray[i] < inputArray[lowest]) lowest = i;
    }
    return lowest;
}

html should look like this

<input id="customRangeInput" type="range" min="5000" max="100000" step="5000" list="valid-options" ng-model="selectedValue" />Selected Value: {{ selectedValue }}</div>
Sign up to request clarification or add additional context in comments.

3 Comments

i guess oninput event is not supported in ie11 . i'll update the code in a minute
Looks like IE11's range input doesn't work with angular, either... github.com/angular/angular.js/issues/6726
i've updated the code . attaching this methods to onchange event nearly solved the problem for ie11 but it works a little buggy because onchange event is not fired instantly like oninput event
1

you need to use property step, that let's you decide how much is every step, for your example, most values are in 25000 so make step="25000"

<input type="range" min="0" max="100000" step="25000">

and to solve the 5000 value... in your example your first value is 5000 what you do is that if you receive 0 that is your low value that is 5000... the other values increase in 25000... hope that helps.

and you don't need the datalist in this case.

2 Comments

Very clever solution. What if I'm not so lucky to have 25,000 increments with only one exception? I've got other options that are not as "tidy"... what if my list of options was 1, 4, 10, 23, 30?
then you have to write something fancy with javascript, like code down here, in other answer, but for this case in particular, I think this is a easy solution.
1

Instead of trying to use the values directly, you can use a map that the range slider operates on - so your ng-model is something like myrangeIndex and when you bind your output element you use rangeValues[myrangeIndex] to get the value back out. Equally when you use the value elsewhere you will need to look it up first. If you know the list of elements might grow/shrink later on, you can use max="{{rangeValues.length}}" so that you only need to update the code in one place. If the values can be calculated from ordinal values, you can simply populate rangeValues when the controller is loaded, e.g. $scope.rangeValues = f(1,100); for any given f.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.