4

I am trying to implement a custom filter that returns items that have a 'completed_date' between two date ranges.

However, I am finding that I need access to $scope inside my filter in order to grab the two dates 'picked' from the datepickers.

I don't think I can use an ng-change function as I have multiple other filters, and therefore need to ensure they all work together.

<select ng-model="userSelect" ng-options="user.id as user.name in usersObj"></select>

<select ng-model="departmentSelect" ng-options="department.id as department.name in deptObj"></select>

<div ng-repeat="post in postsList | dateRange | filter: {user_id: userSelect || undefined}: true | filter: {department_id: departmentSelect || undefined}: true">...</div>

The two datepickers are as follows:

<input type="date" ng-model="to_date">
<input type="date" ng-model="from_date">

And my filter in my controller;

.filter('dateRange', function() {
        return function( items ) {
            var filtered = [];
            var from_date = Date.parse($scope.from_date);
            var to_date = Date.parse($scope.to_date);
            angular.forEach(items, function(item) {
                if(item.completed_date > from_date && item.completed_date < to_date) {
                    filtered.push(item);
                }
            });
            return filtered;
        };
    });

However, I now realise I do not have access to $scope inside my filter, which leads me to think there is a better way of doing this.

Thanks in advance.

2 Answers 2

8

As well as I can analyze your problem. You dont need $scope in your custom filter. Thats why its a custom filter do whatever you want. :)

You just need to pass the models with the filter as parameters, Like

.filter('dateRange', function() {
        return function( items, fromDate, toDate ) {
            var filtered = [];
            //here you will have your desired input
            console.log(fromDate, toDate);
            var from_date = Date.parse(fromDate);
            var to_date = Date.parse(toDate);
            angular.forEach(items, function(item) {
                if(item.completed_date > from_date && item.completed_date < to_date) {
                    filtered.push(item);
                }
            });
            return filtered;
        };
    });

And then use it in your HTML like this.

<div ng-repeat="post in postsList | dateRange : from_date : to_date | filter: {user_id: userSelect || undefined}: true | filter: {department_id: departmentSelect || undefined}: true">...</div>

Hope it helps.

Sign up to request clarification or add additional context in comments.

4 Comments

Hope you can update your code to convert fromDate & toDate into date objects. Because it may not work in case if those are directly passed to your filter in a string format as this problem needs. By the way its good to pass on as parameters.
@ankitPundhir Its not any other value. Its the same thing which is binded to the input ng-model. We just have passed the same model into the custom filter which is view able in your controller. You can do any thing with the model in the custom filter.
it works if i select one day before in fromdate and one day more in todate but if i select the same day in both cases (fromdate and todate) it doesnt show anything, i think is because of the hour ( i have this format: 2016-11-03T08:52:50.932Z). I also had to add Date.parse in item.completed_date : Date.parse(item.completed_date)... any solution ? because now if i want dates between 2-11-2016 and 2-11-2016 i have to select in my input dates 1-11-2016 and 3-11-2016 and i want to select in both cases 2-11-2016
Hi can you please help me to resolve similar issue. stackoverflow.com/a/43972873/6756805
1

Every time you apply a new filter you tell the AngularJS Engine to run $digest which leads to poor performance.

To improve your performance and solve your issues I would suggestion using your filters in the controller, which would make your HTML more readable and likely solve your issue.

EDIT:

Above you have registered your filter to your angular app, not the controller itself. You can use the $filter object in your controller like this:

myApp.filter('dateRange',function(){ ... });

myApp.controller('CtrlName',['$filter', $filter, function(){
    var fromDate = ...;
    var toDate = ...;
    var data = [{ completed_date: ... }, ... ];
    $scope.myArray = $filter('dateRange')(data, fromDate, toDate);
}]);

3 Comments

Could you post some code please? Not sure how my filter is 'not' in the controller?
Thanks for the edit. In my case - the app only has one controller - this page is part of a bigger project not using angular (not ideal I know), so would your approach still make any difference? Upvoted for the extra info by the way
If its just being used a single place, then it probably would not have that big of an impact on your overall performance, but it is always good to follow Best Practices whenever possible.

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.