Adding computed field to every element of array in AngularJS model
I am pulling an array of users into my AngularJS model from a JSON datasource. This data is displayed in a table and I would like to create a column that is calculated from two values ββof an existing user object, without changing my underlying data service.
// My model
function UserListCtrl($scope,$http) {
$http.get('users').success(function(data) {
$scope.users = data;
});
};
In my partial template, I know I can do something like this:
<tr ng-repeat="for user in users">
<td>{{user.data / user.count | number:2}}</td>
</td>
But I would rather add this field to the model, so I can use it like this:
<td>{{user.amplification}}</td>
How do I add a "boost" field to each user in my model?
As an aside, is it possible to use a filter orderBy
for something like this:
<td>{{user.data / user.count | number:2}}</td>
source to share
You can:
-
Immediately after loading the user, run:
$ http.get ('users'). success (function (data) {$ scope.users = data; $ scope.user.amplification () = function () {return $ scope.user.data / $ scope.user.count;}});
And use like {{user.amplification()}}
-
Anywhere in the controller:
$ scope. $ watch ('user', function () {$ scope.userAmplification = $ scope.user.data / $ scope.user.count;} really); $ Http.get
-
Or, if user.data/count doesn't change, do the same as 1., but statically compute:
$ http.get ('users'). success (function (data) {$ scope.users = data; $ scope.user.amplification = $ scope.user.data / $ scope.user.count;});
And OrderBy
can be used for any expression (not counting the result of another filter)
source to share
Adding a second answer as I find it relevant as it is different from my first one.
After a little inspection, I found that the method I originally posted crashes if you try to add new lines dynamically or new elements to the array that depend on the computed value. This is because it $scope.array.forEach()
will only work when the controller is created.
The best way to solve this problem is to create a properly defined object
one that contains the desired parameters. eg.
function Task(id, name, prop1, prop2) {
this.id = id;
this.name = name;
this.prop1 = prop1;
this.prop2 = prop2;
this.computedProperty = function () {
return this.prop1 + this.prop2;
};
}
This is much more flexible as every new object created will have a new property.
The only drawback is that in your ajax-success callback, you need to pass each of your users to the 'Users () constructor.
source to share
What worked for me was to add a loop and add a property to each item in that loop. I used the controller property, but I'm pretty sure you can use the scope as you approach it in the question.
function(result) {
self.list = result;
angular.forEach(self.list, function(item) {
item.hasDate = function() {
return this.TestDate != null;
}.bind(item); // set this context
});
}
Then in my markup I just used it like this.
<div ng-repeat...>
<div ng-show="item.hasDate()">This item has a date.</div>
</div>
source to share