chuck w
chuck w

Reputation: 1761

ng-repeat filter not updating on scope change

Just learning angular, so please excuse the noob nature of this question . . .

I have a list of posts that I want to filter, either alphabetically or based on age (oldest first or youngest first). My code was working before I moved my html into a directive template. Now it's not. Pretty clear that I'm missing something w/r/t the digest cycle.

Check out this plunker to see the problem in action. As you can see, both $scope.predicate and $scope.reverse are being updated, but the filter isn't re-triggering.

HTML:

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src="https://code.angularjs.org/1.2.16/angular.js" data-semver="1.2.16"></script>
    <script src="app.js"></script>
  </head>

<body>
  <div posts></div>
</body>

JS:

var app = angular.module('myApp', []);

app.controller('postsCtrl', ["$scope", function($scope) {

function getPosts() {
  return [{
    "title": "bbbBloter",
    "createdOn": new Date()
  }, {
    "title": "cccBloter",
    "createdOn": new Date(1360000000000)
  }, {
    "title": "aaaBloter",
    "createdOn": new Date(1290000000000)
  }, {
    "title": "dddBloter",
    "createdOn": new Date(1390000000000)
  }, {
    "title": "abcBloter",
    "createdOn": new Date(1280000000000)
  }, ];
}

//load each blotter, then get each blotters' posts, and then set-up the blotter init values
function init() {
  $scope.posts = getPosts();
  $scope.predicate = 'story.last_posting';
  $scope.reverse = true;
  $scope.orderProp = "last_posting";
}

//user has requested a different sorting
$scope.changeSort = function(sortingOn) {
  switch (sortingOn) {
    case "title":
      $scope.predicate = 'story.title';
      $scope.reverse = false;
      break;
    case "last_posting":
      $scope.predicate = 'story.last_posting';
      $scope.reverse = true;
      break;
    case "first_posting":
      $scope.predicate = 'story.last_posting';
      $scope.reverse = false;
      break;
  }
};

init();

}]);

app.directive('posts', function($filter) {
return {
  replace: true,
  template: 
  '<div ng-controller="postsCtrl">' +
    '<div>' +
      'Search: <input ng-model="query">' +
      'Sort by:' +
      '<select ng-model="orderProp" ng-change="changeSort(orderProp)"   >' +
        '<option value="title">Alphabetical</option>' +
        '<option ng-selected=true value="last_posting">Newest</option>' +
        '<option value="first_posting">Oldest</option>' +
      '</select>' +
    '<br>predicate:{{predicate}}; reverse:{{reverse}}<br>' +
    '<ul>' +
      '<li debug ng-repeat="post in posts | filter:query | orderBy:predicate:reverse">' +
        '{{post.title}}' +
        '<p>{{post.createdOn}}</p>' +
      '</li>' +
    '</ul>' +
    '</div>' +
  '</div>',
  link: function(scope){
    scope.$watch("reverse", function(){
      console.log(scope);
    });
  }
};
}
);

Upvotes: 0

Views: 1490

Answers (3)

spacemigas
spacemigas

Reputation: 801

You need to remove the story. from the predicate expressions. I think that this was something you left behind when you move to the directive.

I've forked your plunker here

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691785

Your "predicates" are story.title and story.last_posting. The structure of the items is

  {
    "title": "bbbBloter",
    "createdOn": new Date()
  }

Given that there is no "story" property in the items, it's thus impossible to sort by story.title.

Change your predicates to title and createdOn, and everything will go fine.

Upvotes: 1

Mosho
Mosho

Reputation: 7078

This isn't about digest cycles. What you assign to predicate has nothing to do with your data.

Here's a working plunker.

I changed this part:

$scope.changeSort = function(sortingOn) {
  switch (sortingOn) {
    case "title":
      $scope.predicate = 'title';
      $scope.reverse = false;
      break;
    case "last_posting":
      $scope.predicate = 'createdOn';
      $scope.reverse = true;
      break;
    case "first_posting":
      $scope.predicate = 'createdOn';
      $scope.reverse = false;
      break;
  }
};

Upvotes: 2

Related Questions