apply formatting filter dynamically in a ng-repeat

My goal is to apply a formatting filter that is set as a property of the looped object.

Taking this array of objects:

[
  {
    "value": "test value with null formatter",
    "formatter": null,
  },
  {
    "value": "uppercase text",
    "formatter": "uppercase",
  },
  {
    "value": "2014-01-01",
    "formatter": "date",
  }
]

The template code i'm trying to write is this:

<div ng-repeat="row in list">
    {{ row.value | row.formatter }}
</div>

And i'm expecting to see this result:

test value with null formatter
UPPERCASE TEXT
Jan 1, 2014

But maybe obviusly this code throws an error:

Unknown provider: row.formatterFilterProvider <- row.formatterFilter

I can't immagine how to parse the "formatter" parameter inside the {{ }}; can anyone help me?

See the plunkr http://plnkr.co/edit/YnCR123dRQRqm3owQLcs?p=preview


The | is an angular construct that finds a defined filter with that name and applies it to the value on the left. What I think you need to do is create a filter that takes a filter name as an argument, then calls the appropriate filter (fiddle) (adapted from M59's code):

HTML:

<div ng-repeat="row in list">
    {{ row.value | picker:row.formatter }}
</div>

Javascript:

app.filter('picker', function($filter) {
  return function(value, filterName) {
    return $filter(filterName)(value);
  };
});

Thanks to @karlgold's comment, here's a version that supports arguments. The first example uses the add filter directly to add numbers to an existing number and the second uses the useFilter filter to select the add filter by string and pass arguments to it (fiddle):

HTML:

<p>2 + 3 + 5 = {{ 2 | add:3:5 }}</p>
<p>7 + 9 + 11 = {{ 7 | useFilter:'add':9:11 }}</p>

Javascript:

app.filter('useFilter', function($filter) {
    return function() {
        var filterName = [].splice.call(arguments, 1, 1)[0];
        return $filter(filterName).apply(null, arguments);
    };
});

I like the concept behind these answers, but don't think they provide the most flexible possible solution.

What I really wanted to do and I'm sure some readers will feel the same, is to be able to dynamically pass a filter expression, which would then evaluate and return the appropriate result.

So a single custom filter would be able to process all of the following:

{{ammount | picker:'currency:"$":0'}}

{{date | picker:'date:"yyyy-MM-dd HH:mm:ss Z"'}}

{{name | picker:'salutation:"Hello"'}} //Apply another custom filter

I came up with the following piece of code, which utilizes the $interpolate service into my custom filter. See the jsfiddle:

Javascript

myApp.filter('picker', function($interpolate ){
    return function(item,name){
       var result = $interpolate('{{value | ' + arguments[1] + '}}');
       return result({value:arguments[0]});
    };
});