1

I'm working on learning Angular JS by creating my own app. My focus is Angular, so I'm not connecting to a database like one would in the real world - thus I have an array of movies = [{title: '', genre: '', rating: ''}...] hard coded into my js file.

I have a series of buttons with the different movie ratings: G, PG, PG13, R. Each button should work as a filter and then return movies who's rating matches the button. When the button is clicked, Data.selectedRating stores the value. However, I'm running into trouble with the built-in filter because if there are no movies with the desired rating, it will return all of them when it should return none. And if the "PG" button is clicked it returns movies with the rating of PG and PG13.

Is there a way to fix this? I thought I may need to make a custom filter, but I'm not really sure how to go about it (as I'm sure you'll be able to tell). Any suggestions? Thanks!

Here's what I have:

HTML

// Data.selectedRating holds the value of the button that was clicked 
// Built in filter looked like this: 
// ng-repeat="movie in movies | filter: Data.selectedRating"
<table>
    <tr ng-repeat="movie in movies">
        <td>
            {{movie.title | filterRating}}
        </td>
    </tr>
</table>

JS

angular.module('movieApp', ['ngAnimate', 'ui.router'])
.factory('Data', function() {

       return { sortType: '', 
                selectedGenre: '',
                selectedRating: ''};
 })

.controller('formController', ['$scope', 'Data', function($scope, Data) {

   $scope.Data = Data;

   $scope.movies = [
    {title:'Pitch Perfect 2', genre: 'Musical', rating: 'PG13'},
    {title:'Longest Ride', genre: 'Romance', rating: 'PG13'},
    {title:'Furious 7', genre: 'Action', rating: 'PG13'},
    {title:'Home', genre: 'Adventure', rating: 'PG'},
    {title:'Insurgent', genre: 'Action', rating: 'PG13'}
    ];
 }])

.filter('filterRating', function() {

    var out = [];
    return function(selectedRating, a) {

        if(selectedRating.rating == Data.selectedRating)
        {
            out.push(selectedRating.title);
        }
    }
    return out;
});

============================================

Update - I have added the suggestions by a few of the comments below - Thanks! Now, instead of the name of the movie, "undefined" is return. Any ideas?

Updated Code: HTML:

...
<td>
    {{movie.title | filterRating}}
</td>
...

JS

.filter('filterRating', function() {

    return function(selectedRating, movies) {

        var out = [];

        if(Data.selectedRating == selectedRating.rating)
        {
            alert(' in here');
            out.push(movies.title);
        }
        return out;
    }
});
5
  • You need to put the var out = []; and return out lines inside the filter's function. You'll also have to take the array of movies as an argument, and iterate over it. Compare your solution with stackoverflow.com/a/15197233/624590 for more details. Commented May 15, 2015 at 0:49
  • possible duplicate of AngularJS - How to structure a custom filter with ng-repeat to return items conditionally Commented May 15, 2015 at 0:51
  • Thanks @DRobinson! That helped! I edited my post w/ the edits. Now it returns 'undefined' instead of the movie names. Do you know why? Thanks! Commented May 15, 2015 at 1:00
  • HTML can be <tr ng-repeat="movie in movies | filterRating:Data.selectedRating"> . Filter can be function(movies, selectedRating){ var out = movies.filter(function(movie){ return movie.rating === selectedRating; }); return out; }. (The inner filter call is Array's prototype filter, not angular's filter) Commented May 15, 2015 at 1:07
  • Wow! You're awesome @DRobinson! Thanks so much! It worked! If you put your comment in an answer, I'll mark it correct! Thanks so much! I really appreciate it! Commented May 15, 2015 at 1:13

2 Answers 2

2

You filter function should be like this

.filter('filterRating', function() {
  return function(movies) {
    var out = [];

    angular.forEach(movies, function(movie) {
      if (movie.rating == Data.selectedRating)  out.push(movie);
    });
    return out;
  }
});
Sign up to request clarification or add additional context in comments.

Comments

1

Your code should be :

HTML

 <tr ng-repeat="movie in movies | filterRating ">
      <td>
          {{movie.title }}
      </td>
  </tr>

JS

.filter('filterRating', function(Data) {


return function(selectedRating) {
  var out = [];
    for (var i = 0; i < selectedRating.length; i++) {

      if(selectedRating[i].rating == Data.selectedRating)
      {
        out.push(selectedRating[i]);
      }

    }
    return out;
}

});

The reason for it, is that you want to filter the movie object and not the title itself

PLUNKR : http://plnkr.co/edit/nYAX9kiBhqYyXCqaMYhc?p=preview

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.