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>

      

+3


source to share


4 answers


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)

+2


source


If you don't need your function amplicification()

to update on properties data

and count

in your update user

, you can do something like this in your controller:



$scope.users.forEach(function(user) {

    user.amplification = function() {

        return user.data / user.count;

    };

});

      

+1


source


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.

0


source


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>

      

0


source







All Articles