In Angular, you can easily format variables using filters, such as these:
{{ myDate | date }}
{{ myMoney | currency }}
Is there any way to programmatically set the type of the filter so that it looked something like this?
// controller
$scope.myFilter = 'date';
// view
{{ myVar | myFilter }}
Context: I'm returning tabular data from my server along with some meta information. I'd like to display things like dates, money, or numbers without having to hand-code the columns.
Here's a link to a very simple, and non-functional Plunker of this problem: http://plnkr.co/edit/SjYLKKUZcTjzRFhbsjK0
You could wrap your filters up into a 'table cell filter' or similar, and switch on a filter parameter - which could be controlled programmatically.
Here is a quick example:
http://plnkr.co/edit/1DGOC1gFZiFyGAQRCIhk?p=preview
In your template:
<ul>
<li ng-repeat="value in values">{{value | myfilter:myFilterType }}</li>
</ul>
The filter:
app.filter('myfilter', function() {
return function(input, type) {
switch(type) {
case 'uppercase':
return input.toUpperCase();
case 'lowercase':
return input.toLowerCase();
case 'date':
return input.toString('dddd, MMMM ,yyyy');
}
};
});
Note that if required, you could load other filters and apply them to the input inside that one, so that your code is clean and DRY.
You can apply filters programmatically, but I don't think it's possible to do it that way. If you're OK with defining filtered values inside the controller, then you might do it like this:
JS:
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope, $filter) {
$scope.values = [new Date(-1), new Date()];
$scope.myFilter = 'date';
$scope.$watch('values', function(values){
$scope.filteredValues = [];
if(!angular.isArray(values)){
return;
}
angular.forEach(values, function(value){
$scope.filteredValues.push($filter($scope.myFilter)(value));
});
});
});
HTML:
<div ng-controller="MainCtrl">
<ul>
<li ng-repeat="value in filteredValues">{{value}}</li>
</ul>
</div>
A much simpler alternative is to just call a function when you display the value. This way you can reuse the $filter service and also add your own logic. See plunker.
app.controller('MainCtrl', function($scope, $filter) {
$scope.values = ['Test #1', 'Test #2'];
$scope.myFilter = 'uppercase';
$scope.myFilterFn = function(value) {
console.log(value);
var filter = $filter($scope.myFilter);
console.log(filter);
return filter(value);
};
});
Template:
<body ng-controller="MainCtrl">
<p>{{myFilter}}</p>
<button ng-click="myFilter = 'uppercase';">Uppercase</button>
<button ng-click="myFilter = 'lowercase';">Lowercase</button>
<p>
<ul>
<li ng-repeat="value in values">{{myFilterFn(value)}}</li>
</ul>
</p>
</body>