3

I have an array of objects. The only exposed interface of these objects are their methods.

obj = { 
  getId : function() { ... },
  getName : function() { ... },
  getAvgHours : function() { ... }
}

In fact, there are some fields that contain the actual values. But these are generated code so these fields are cryptically named, are buried under another layer of field. The access to their values should be done via supplied functions only.

I'm looking for something like below, but it doesn't work:

<tr ng-repeat="p in people | orderBy:p.getAvgHours()">

I could add a named function getAvgHours(p) { return p.getAvgHours(); } to the scope, which works. But it seems redundant, and I'd need to add a dozen of these functions.

Is there any better way?

2 Answers 2

1

You could simply make use of a predicate and pass the method you wish to call as a string.

The markup:

orderBy:fnValue('getId')

And the predicate function:

$scope.fnValue = function (fn) {
    return function (obj) {
        return obj[fn]();
    };
};

Inside the function you return from the predicate, you will have access to the object being sorted, so you would invoke the method there and fetch the value.

DEMO

Sign up to request clarification or add additional context in comments.

2 Comments

@Gant In isolation I agree this is a better answer. However, if you're planning to do this type of filtering in more than one view than my solution is DRYer. As this solution will always need a reference in the view's controller.
@Jack Totally agree with you. Once I need to use this in more places, I think I might shift to your solution eventually.
1

There may be a better way, but one solution would be to write your own filter that wraps the normal orderBy. Here's an example:

myApp.filter("orderByObjFunc", ["$filter", function($filter) {
  return function(input, funcName, reverse) {
      input = input.map(function(a) { a.zSortField = a[funcName](); return a; });
      return $filter('orderBy')(input, 'zSortField', reverse);
  };
}]);

This would save you from making a dozen helper functions. You'd use it like this:

 <tr ng-repeat="p in people | orderByObjFunc:'getAvgHours'">

Here's a working fiddle.

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.