IcedBlind IcedBlind - 3 months ago 38
AngularJS Question

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

Answer

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);
    };
});