Tom
Tom

Reputation: 1565

Pass function as select value in AngularJS

I have a list of films that I want to sort by a choice from a dropdown list. I'm using a custom function to do the sorting to exclude non-numeric options. It works fine when passing the function directly but I'm not sure how to pass that function as a value in the dropdown.

    <select name="sort" id="" ng-model="filters">
        <option value="sortByRtRating">Rotten Tomatoes rating</option>
        <option value="sortByImdbRating">IMDB rating</option>
    </select>

<div ng-repeat="movie in movieList | toArray | orderBy:filters.sort:true">

$scope.sortByRtRating = function(item) {
  if (!item.details) return -1;
  if (typeof item.details.rt.rating != 'number')
    return -1;
  return item.details.rt.rating;
}  

$scope.sortByImdbRating = function(item) {
  if (!item.details) return -1;
  if (typeof item.details.imdb.rating != 'number')
    return -1;
  return item.details.imdb.rating;
} 

Upvotes: 0

Views: 778

Answers (1)

New Dev
New Dev

Reputation: 49590

There are 2 ways to solve this - depending on how you implement the select - and thus what the select's ng-model will hold.

#1 - with function names as the ng-model of select

When you create a select with normal <options> - i.e. without ng-options (as you did) - the ng-model can only hold the function name as a string - which is a value of the <option>.

<select ng-model="filterFnName">
  <option value="sortByRtRating">Rotten Tomatoes rating</option>
  <option value="sortByImdbRating">IMDB rating</option>
</select>

Then you need to $eval to get the function out of the function name (the functions need to be exposed on the scope):

<div ng-repeat="movie in movieList | orderBy:$eval(filterFnName):true">{{movie}}</div>

#2 - with function as the ng-model of select

This is only possible with ng-options as Angular can bind to a complex object (including functions).

You can define the following in your controller:

$scope.filterFns = [
    {l: "Rotten Tomatoes rating", fn: sortByRtRating}, 
    {l: "IMDB rating", fn: sortByImdbRating}
];
$scope.filterFn = sortByRtRating;

function sortByRtRating(item){...}

function sortByImdbRating(item){...}

And you can select and use the actual function object:

<select ng-model="filterFn" ng-options="f.fn as f.l for f in filterFns">
</select>

<div ng-repeat="movie in movieList | orderBy:filterFn:true">{{movie}}</div>

plunker

Upvotes: 1

Related Questions