Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Marc Murray
Marc Murray
4,618 Points

Calling Angular heads, I'm stuck! Custom ng-filter for matching date value in scope.

Hi everyone! I'm trying ti improve on the To Do list application created in the AngularJS course here on treehouse, I've done a couple of things and am now trying to add real dates etc to the app. I'm trying to create a custom filter that will check the properties of items in an ng-repeat against some pre defined dates I have in the defined in the controller. The dates are today, tomorrow and next week. The filter should enable me to repeat only todays tasks into the today div, tomorrow into tomorrows etc. I'm looking to end up with something like this in the markup:

<li class="{{todo.category}}" ng-repeat="todo in todos | taskDate : today"> {{todo.title}} <li> However I can't quite get it to work, I'm unfamiliar with checking properties against values in the scope, and I think that is my main issue here.

Example todo structure: (dates are generated through the AngularUI bootstrap directives so not 100% on how they are formatted.)

$scope.todos = [
{name : 'Complete 5 tasks',
category: 'Life',
date: ''}
]

The dates:

// dates
$scope.todaysDate = new Date();
$scope.tomorrowsDate = new Date();
$scope.nextWeeksDate = new Date();
$scope.tomorrowsDate.setDate($scope.tomorrowsDate.getDate() + 1);
$scope.nextWeeksDate.setDate($scope.nextWeeksDate.getDate() + 7);

The filter I have written for now (verging on psuedo code):

app.filter("taskDate", function() {
    return function(input, date) {
        if (date === 'today') {

            if ($scope.todo.date === $scope.todaysDate) {
                return input;
            }
        else if (date === 'tomorrow') {

            if ($scope.todo.date === $scope.tomorrowsDate) {
                return input;
            }
            else {
                return 'nope';
            }

        }
        else {
            return 'nope';
        }
    };
});

I'm pretty certain the selectors in my if statement are far off what they should be ($scope.todo.date etc), could anyone recommend a solution?

Matthew Batman
Matthew Batman
30,187 Points

I think that your filter doesn't "know" about your $scope variables or their values. Your $scope variables, I think, live inside your controller (this doesn't apply to $rootScope).

I think your going to have to write your filter to accept another variable, where your provide that filter your $scope variable -- just like your doing with the input and date parameters.

1 Answer

Seth Kroger
Seth Kroger
56,413 Points

There are a couple things to go over here so bear with me.

First, Date objects in JavaScript aren't just dates, but date and time down to the millisecond. So suppose todaysDate is 4/8/2016 19:37:43.839 and the todo item's date is 4/8/2016 23:59:59.000. It should obviously be selected for today but won't be because the dates aren't exactly equal. What you should check instead is if the todo's date is in the range of 00:00:00.000 and 23:59.59.999 on that date.

Second, you should really find out how the date is stored in the todo item so there aren't any suprises. Is it a Date, string, or number? If it's not a Date it would need to be converted into one.

Third, as far as accessing $scope from your custom filter, you don't (meaning more shouldn't than can't). You're already passing in the necessary informaton from $scope (the todos list) to the filter function. You can access your todos' dates through input instead of $scope, and there's nothing special about today's or tomorrow's date that they can't be recreated inside the function.

Fourth, the way you wrote your filter you're assuming ng-repeat passes one todo item at a time It is actually passed the entire todos array with the expectation you'll be returning an altered array. It your case you would build an output array only including the items that matched your criteria.

Fifth, but wait. There's already a filter that does what you want, called filter. (Don't look at me like that; I didn't name these.) It can be passed string or object to match items in the array against or a function that's called for each item in the array and returns true or false as to whether to include the item in the output array. You can supply this function from your controller and access $scope from it as much as you like.