Search code examples
angularjsmomentjsangularjs-ng-clickangular-directiveangular-filters

Paginate By Week - AngularJS


I am trying to paginate a list of events (using ng-repeat) by week in AngularJS. I have a custom filter working that only displays the events within the current week, but I am trying to add functionality to look at future and past weeks.

Here is the filter I am using for the event lists -

$scope.week = function(item) {
    var weekStart = moment().startOf('week');
    var weekEnd = moment().endOf('week');
    var eventTime = moment(item.jsdatetime);
        if (eventTime >= weekStart && eventTime <= weekEnd) return true; 
            return false;
};

I have tried using ng-click to call a function that uses moment.js to .add(7, 'days'); to the weekStart and weekEnd variables but can't seem to get it to work.

Any help would be appreciated.

Here's a CodePen with the basic functionality going on - http://codepen.io/drewbietron/pen/xbKNdK


Solution

  • The moment() always return the current date/time.

    You need to store a reference to it to a variable, and then use that for manipulations.
    (and since you have other variables depending on it, i would create a function that sets all those variables at once)

    So in the controller i changed the top part to

    var currentDate,
        weekStart,
        weekEnd,
        shortWeekFormat = 'MMMM Do';
    
    function setCurrentDate(aMoment){
      currentDate = aMoment,
      weekStart = currentDate.clone().startOf('week'),
      weekEnd = currentDate.clone().endOf('week')
    }
    
    // initialize with current date
    setCurrentDate(moment());
    
    // use these methods for displaying 
    $scope.currentWeek = function(){ return currentDate.format(shortWeekFormat); }; 
    $scope.currentWeekStart = function(){ return weekStart.format(shortWeekFormat); };
    $scope.currentWeekEnd = function(){ return weekEnd.format(shortWeekFormat); };
    

    Then create two methods for going to next/previous week

    $scope.nextWeek = function(){
      setCurrentDate(currentDate.add(7,'days'));
    };
    $scope.prevWeek = function(){
      setCurrentDate(currentDate.subtract(7,'days'));
    };
    

    (moment.js implements valueOf so you do direct comparisons)
    And finally change your week filter to actually compare the dates (using .isSame(), .isBefore() and .isAfter()) instead of the moment objects (which was wrong as you cannot do direct comparisons on custom objects)

    $scope.week = function(item) {
        var eventTime = moment(item.jsdatetime);
    
        if ((eventTime.isSame(weekStart) || eventTime.isAfter(weekStart))&& 
            (eventTime.isSame(weekEnd) || eventTime.isBefore(weekEnd))) return true; 
    
        return false;
    };
    

    $scope.week = function(item) {
        var eventTime = moment(item.jsdatetime);
    
        return (eventTime >= weekStart && eventTime <= weekEnd);
    };
    

    (you also, most likely, want the ng-repeat on the li elements and not the ul)

    Demo at http://codepen.io/gpetrioli/pen/QwLRQB