Search code examples
jqueryangularjsdatetimeangularjs-directiverangeslider

Angular Time range slider


I am using http://danielcrisp.github.io/angular-rangeslider/demo/ to create a range slider but I would like it to use time(HH:MM) not just plain numbers. So it would range from 10m - 2hr. However I am a bit confused about how to achieve this.

Would I be better off formatting the time like this:

$scope.minTime = 10;
$scope.maxTime = 120;

The time is calculated in minutes then perhaps I could somehow maybe using the date filter convert the numbers into hh:mm but I would still prefer if it were formatted something like (10min, 30min, 1hr, 1hr 10min, 1hr 30min, 2hr)

Or is this a better way to do it:

$scope.minTime = 00:10;
$scope.maxTime = 02:00;

Or have I completely missed this and there is a better way?


Solution

  • The best options seems to be storing the values as minutes and displaying them using a custom filter.

    <div ng-controller="myCtrl">
        <div range-slider pin-handle="min" attach-handle-values
             prevent-equal-min-max step="{{sliderConfig.step}}"
             min="sliderConfig.min" max="sliderConfig.max"
             model-min="sliderConfig.userMin" model-max="sliderConfig.userMax" 
             filter="hourMinFilter">
        </div>
    </div>
    
    app.controller('myCtrl', function ($scope) {
        $scope.sliderConfig = {
            min:  0,
            max:  120,
            step: 10,
            userMin: 0,
            userMax: 30
        };
    });
    
    app.filter('hourMinFilter', function () {
        return function (value) {
            var h = parseInt(value / 60);
            var m = parseInt(value % 60);
    
            var hStr = (h > 0) ? h + 'hr'  : '';
            var mStr = (m > 0) ? m + 'min' : '';
            var glue = (hStr && mStr) ? ' ' : '';
    
            return hStr + glue + mStr;
        };
    });
    

    See, also, this short demo.


    UPDATE:

    A modified version to allow a customizable filter max-value and show a different literal (by popular demand):

    1) Extend the filter to receive a second argument: the max limit.

    ...
    return function (value, max) {
        if (value == max) { return 'All'; }
    
        var h = parseInt(value / 60);
        var m = parseInt(value % 60);
        ...
    

    Note: The use of == instead of === is very important in order to check a string representation of the number against an actual number. If you want to avoid using ==, you should first convert both arguments to either String or Integer.

    2) Modify the HTML to include the extra filter argument:

    <div range-slider pin-handle="min" attach-handle-values
         ....
         filter="hourMinFilter" filter-options="{{sliderConfig.max}}">
    </div>
    

    See, also, this updated demo.