AngularJS filtering between a range
Asked Answered
P

1

6

I have set up a range slider that ranges from 0 - 2hr, the times are calculated in mins then converted to hh:mm like this: 10min, 20min, 1hr 20min, 2hr.

But now I am trying to filter a bunch of items inside the ng-repeat using the range specified by the range slider and I am having a hard time getting this working.

Here is what I have done http://cdpn.io/LDusa

I am using http://danielcrisp.github.io/angular-rangeslider/demo/ for the range slider.

And here is the code:

var app = angular.module('myApp', ['ui-rangeSlider']);
app.controller('myCtrl', function ($scope) {
    $scope.sliderConfig = {
        min:  0,
        max:  120,
        step: 10,
        userMin: 0,
        userMax: 30
    };

   $scope.times = [
      {"time": "20"},
      {"time": "50"},
      {"time": "30"},
      {"time": "10"},
      {"time": "85"},
      {"time": "75"},
      {"time": "95"},
      {"time": "100"},
      {"time": "80"},
      {"time": "200"},
      {"time": "260"},
      {"time": "120"},
      {"time": "62"},
      {"time": "68"},
      {"time": "5"},
      {"time": "116"}
   ];
});

app.filter('customFilter', 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;
    };
});

app.filter('range', function() {
  return function(input, min, max) {
    min = parseInt(min);
    max = parseInt(max);
    for (var i=min; i<=max; i++)
      input.push(i);
    return input;
  };
});

JADE(If you prefer HTML you can convert it back to html using this http://html2jade.org/):

div(ng-app="myApp")
  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='customFilter')


    div(range-slider, prevent-equal-min-max='', attach-handle-values='',  min='sliderConfig.min', max='sliderConfig.max', model-min='sliderConfig.userMin', model-max='sliderConfig.userMax', filter='customFilter')

    div(ng-repeat="time in times | range:sliderConfig.userMin:sliderConfig.userMax")
      | {{ item.time | customFilter }}

How can I get this working so it will only display items when time is within the range specified in the range slider?

Parnas answered 19/5, 2014 at 1:47 Comment(1)
You could wrap your items with an ng-show in conjunction with a range condition. I modified your example to demonstrate what I mean - codepen.io/anon/pen/ApvcFHidie
T
9

Pass the sliderConfig into the filter to find the current min and max set on the range slider. Make sure your objects are in an array.

    <div range-slider="range-slider" 
         min="sliderConfig.min" 
         max="sliderConfig.max" 
         model-min="sliderConfig.userMin" 
         model-max="sliderConfig.userMax">
    </div>
    ...
    // Pass the slider config into the filter
    <div ng-repeat="time in times | rangeFilter:sliderConfig">
        {{ time.time | customFilter}}
    </div>
    ...
    $scope.times = [
      {time: '20'},
      {time: '50'},
      ...
    ];

The rangeFilter has the second parameter 'rangeInfo' which we can get the 2 values from.

app.filter('rangeFilter', function() {
    return function( items, rangeInfo ) {
        var filtered = [];
        var min = parseInt(rangeInfo.userMin);
        var max = parseInt(rangeInfo.userMax);
        // If time is with the range
        angular.forEach(items, function(item) {
            if( item.time >= min && item.time <= max ) {
                filtered.push(item);
            }
        });
        return filtered;
    };
});

Hope it helps.

Tancred answered 19/5, 2014 at 2:58 Comment(7)
This is works perfectly, I just have one question. Is it possible to make this work with multiple range sliders. I have tried to achieve this cdpn.io/LDusa but I'm not sure how to set up the filter on the ng-repeat now that it calls sliderConfig in the rangeFilter. I think i would need to some how have secondTimeConfig in with the SliderConfig but I am not sure.Parnas
I have added some extra info to the answerTancred
With 2 range sliders the idea is if I start filtering times between a range 20min - 1hr 20min then I use the second range slider to find items with in that 20min - 1hr 20min range that have a 'secondTime' between 10min - 100min. I don't want to overwrite the first slider when I use the second, I would like them both to be able to filter the information with respect to each other. It looks like you are checking if maxOne and maxTwo are different and then filtering based on that. And I'm not sure that will work quite how I am wanting. Please correct me if I am wrong as I would like to learn.Parnas
Tried that out but I couldn't get it working. cdpn.io/LDusa I also changed from JADE to HTML incase you might find it easier.Parnas
Perhaps this might make things a bit clearer, I have set up a plunker embed.plnkr.co/jHtvnHxnmb5s6V36rJJY/preview I have added a comment in the code about what seems to be breaking the filter. But hopefully it will just make it clear as to what I am trying to achieve.Parnas
This makes a lot more sense now. plnkr.co/edit/j5nrgw8vD0NepvvzJcyO?p=previewTancred
Thanks that makes perfect sense and works really well. Appreciate the helpParnas

© 2022 - 2024 — McMap. All rights reserved.