0

I need to get the total of the following example:

$scope.fees = {
    basic: 1,
    premium: 2,
    total: this.basic + this.premium
}

Why won't this work? It says this is undefined. Is there a way to achieve this without having to write out total: $scope.fees.basic + $scope.fees.premium.

I'd love if there was a way to shorten it.

EDIT: I'd actually have to add the total property outside of $scope.fees. $scope.fees.total = ...

jstudios
  • 856
  • 1
  • 9
  • 26
  • 1
    This question is very imprecise. It asks about "How to access", but clearly you know *how* - you just want to shorten it. So, are the answers to be judged by least amount of characters? Not to mentioned, that the entire question could have been asked without ***any*** reference to AngularJS or "scope" tags – New Dev May 12 '15 at 20:11
  • possible duplicate of [How does "this" keyword work within a JavaScript object literal?](http://stackoverflow.com/questions/133973/how-does-this-keyword-work-within-a-javascript-object-literal) – New Dev May 12 '15 at 20:15
  • Until the closing brace of fees is processed, $scope.fees does not exist yet and hence cannot be accessed. – Nagasimha Iyengar May 12 '15 at 20:15

3 Answers3

2

You can use function ..

Hello {{ total() }}
function FeeController($scope) {

    $scope.fees = {
    basic: 1,
    premium: 2,

};

  $scope.total = function() {
    return $scope.fees.basic  + $scope.fees.premium;
  };

}
1

Why this.basic doesn't work

this is evaluated in the context of the function that contains this statement. So this doesn't refer to the $scope.fees object, but to the controller.

Why total : $scope.fees.basic + $scope.fees.premium doesn't work either

At the moment that the expression $scope.fees.basic + $scope.fees.premium is evaluated the $scope.fees object doesn't exist yet, because you're in the middle of creating it. Therefore it will result in an error like "Cannot read property basic of undefined".

How to solve this

There isn't any solution other than what you've already found that results in the behaviour you want, so unfortunately you'll have to stick with it.

Tiddo
  • 6,331
  • 6
  • 52
  • 85
0

You might consider using the "controller as class" pattern which lessens your dependency on the $scope. You could do something like this:

app.controller('FeeCtrl', function () {
  this.basic =1;
  this.premium =2;
  this.total = this.basic + this.premium;
});

Then you can inject this controller right into your dom:

<div ng-controller="FeeCtrl as fee">   
 {{ fee.total }} 
</div>

There are more detailed instructions here

http://toddmotto.com/digging-into-angulars-controller-as-syntax/

Robert Moskal
  • 21,737
  • 8
  • 62
  • 86
  • Yours is not a bad suggestion, but controller as or scope makes no difference here. If you substitute `$scope` for `this` in your example it is essentially the same. Though at least controller as could make things shorter, which seems to be the goal of the OP. – Tim Hobbs May 12 '15 at 20:20
  • except since you aren't constructing an object literal, this.basic, etc is immediately available. – Robert Moskal May 12 '15 at 20:23
  • Yeah, I get that, but it would be the same with `$scope` as well. The point is that the object literal cannot be used the way the OP wants, not that controller as vs. `$scope` makes it behave differently, wouldn't you agree? – Tim Hobbs May 12 '15 at 20:24
  • agreed, in fact the @Ramakrishna Kudikala answer is the closest to simply solving the problem, though I think that there's no reason for total to be a function. – Robert Moskal May 12 '15 at 20:27
  • True, but I do think your controller as suggestion is a good one. With angular 2 scope goes away, and unless you need to do emits or broadcasts, eliminating scope is a good thing IMHO. – Tim Hobbs May 12 '15 at 20:28