4

Here is the code for my angular code:

  angular.module('ngApp', [])
  .factory('authInterceptor', authInterceptor)
  .constant('API', 'http://appsdev.pccportal.com:8080/ecar/api')
  .controller('carDetails', carDetails)

  function carDetails($scope, $http, API) {
    $http.get( API + '/car/12208' ).
    success(function(data) {
      $scope.details = data;
    });
  }

Here is a pic of the JSON data I am working with:

enter image description here

As you can see under Financial Info I have multiple keys that have currency values in them. How can I pull out those values in angular and add them together and then display that result in my HTML file.

I can obviously get land_curr and land_prev values in the html by using

{{ details['Financial Info'].land_curr }}

But in the HTML that I have been given there is a spot for "total amount". So I need to take those values, add them together and then put that new value into the "total amount" section in the HTML file.

Is there a way I can do this?

EDIT:

Note that these JSON values will change so I cant "hard code" the currency values into anything as the currency amounts will change often. Also I need to be able to add all "_prev" values together and "_curr" values together. And I need to just be able to add, for instance, "land_curr" and "land_prev" together too.

5 Answers 5

2

Since JS is a dynamic language you can add a new property/method to 'Financial Info' that does the mathematics. like:

  details['Financial Info'].calcTotalLand= function(){return this.land_prev+ this.land_curr;};

you can also just write in your HTML

{{ details['Financial Info'].land_curr + details['Financial Info'].land_prev}}

if possible

Sign up to request clarification or add additional context in comments.

2 Comments

{{ details['Financial Info'].land_curr + details['Financial Info'].land_prev}} ..... just puts the values next to each other. I need to add them together. As far as the first option you showed where would I put that and then how would I pull that into my HTML file
Thank you for getting me started with the solution. I figured it out based on your starting point. See my accepted answer.
2

I would recommend calling a function from your html to get the total. That way, if the values in your 'Financial Info' object change dynamically, the total would be updated as well. See the example I have provided below. (I also threw in an ng-repeat to list all of the 'Financial Info', as well as the currency filter in case you didn't know about those).

In the example, I just hard coded your example object into the $scope.details variable. In your actual application, you can still populate this the same way you were - using the $http service to call your API.

You can add a function, called getTotal() for example, to the controller's $scope. That way, you can call it directly from your html using {{getTotal()}}.

In the getTotal() method, you can just utilize angular's built in forEach() method (or just plain old vanilla javascript if you prefer) to loop through every item in the 'Financial Info' object. Then, you just need to call parseInt() passing in the value, since they are strings in your object, then add it to a running sum variable. Finally, you can return the sum after angular's forEach() is complete.

EDIT: Added methods for getting the total of all _curr values and _prev values, as well as land_.

EDIT 2: Added a timeout to simulate the data loading via your $http call. To avoid getting the error with $scope.details being null until your $http call returns, you can either add if (!$scope.details) { return; } at the beginning of each of your getTotal functions, or you could initialize $scope.details with null or blank values for each of the items that you expect your $http call to return. For example, in the snippet below, I initialized the $scope.details variable as such:

$scope.details = {
  'Executive Summary': null,
  'Financial Info': {},
  ID: null
};

Working Example:

angular.module('ngApp', [])
  .controller('carDetails', carDetails);

function carDetails($scope, $timeout) {
  $scope.details = {
    'Executive Summary': null,
    'Financial Info': {},
    ID: null
  };

  $scope.loading = true;
  $timeout(function() {
    $scope.details = {
      'Executive Summary': "This is a test. Please ignore.",
      'Financial Info': {
        alt_curr: "1000",
        alt_prev: "500",
        auto_curr: "2100",
        bldgs_curr: "12000",
        bldgs_prev: "5000",
        land_curr: "30000",
        land_prev: "700",
        machine_curr: "25000",
        machine_prev: "1000",
        other_curr: "2659",
        other_exp_curr: "900",
        other_exp_expl: "9800",
        other_exp_prev: "600",
        other_prev: "6000",
        startup_curr: "600",
        startup_prev: "550"
      },
      ID: 12208
    };
    $scope.loading = false;
  }, 5000);

  $scope.getTotal = function() {
    var sum = 0;
    angular.forEach($scope.details['Financial Info'], function(value, key) {
      sum += parseInt(value, 10);
    });
    return sum;
  }

  $scope.getCurrTotal = function() {
    var sum = 0;
    angular.forEach($scope.details['Financial Info'], function(value, key) {
      if (key.substring(key.length - 5) == '_curr') {
        sum += parseInt(value, 10);
      }
    });
    return sum;
  }

  $scope.getPrevTotal = function() {
    var sum = 0;
    angular.forEach($scope.details['Financial Info'], function(value, key) {
      if (key.substring(key.length - 5) == '_prev') {
        sum += parseInt(value, 10);
      }
    });
    return sum;
  }

  $scope.getLandTotal = function() {
    var sum = 0;
    angular.forEach($scope.details['Financial Info'], function(value, key) {
      if (key.substring(0, 4) == 'land') {
        sum += parseInt(value, 10);
      }
    });
    return sum;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ngApp" ng-controller="carDetails" ng-cloak>
  <div ng-show="!loading">
    <div ng-repeat="(key, value) in details['Financial Info']">
      <span>{{key}}: {{value|currency}}</span>
    </div>
    <hr/>
    <span>TOTAL: {{getTotal()|currency}}</span>
    <br>
    <span>Current Total: {{getCurrTotal()|currency}}</span>
    <br>
    <span>Previous Total: {{getPrevTotal()|currency}}</span>
    <br>
    <span>Land Total: {{getLandTotal()|currency}}</span>
  </div>
  <div ng-show="loading">
    Simulating data loading by using a timeout...
  </div>
</div>

12 Comments

but these values will change often. I need it to pull in the new values that might have changed on the database. These are "hard coded" values aren't they?
I only hard coded them for this example, because the API you are using is unreachable in the snippet. In your case, the only difference would be you would use your API to populate the $scope.details variable.
What's the deal with using angular.forEach? Why not just Array.prototype.forEach (i.e. functor), or better yet Array.prototype.reduce?
Ahh, never mind, I see now it's looping through an object, my bad.
But still, this is clearly a job for reduce. So either convert the object to a list of values and then sum it or both at the same time: Object.keys(obj).reduce(function(sum, key) {return sum + parseInt(obj[key])}, 0)
|
0

Did you try forEach in Angular ? See below:

angular.module('myApp', []).controller('carDetails', ['$scope', function(scope) {
             var vm = this;
             vm.obj = {'Financial Info':{
                alt_curr : "1000", alt_prev : "2000"
             }}
             vm.sum = 0;
             angular.forEach(vm.obj['Financial Info'], function(val, key){
                vm.sum +=parseInt(val);
             });
             console.log(vm.sum)
         }]);

Edit: In your html, you can display the variable as shown below:

<html>
<div ng-app="myApp" ng-controller="carDetails as vm">
{{vm.sum}}
</div>
</html

4 Comments

Don't you mean vm.sum += parseInt(val);?
Edited. Naming convention issue. That was val, key pair (1000, alt_curr).
the JSON values will be different depending on which "car" is accessed. And can be changed at any time. And If I am seeing this correctly you have given "alt_curr" a specific value. I need to pull the value from the JSON keys and then add them together. So the 1000 and 2000 will change from time to time.
That's fine, when you iterate on the 'Financial Info' object, you'll read all dynamic values. I just created an object for your understanding :)
0

Unfortunately, if the keys in your list can be altered at any time, you could never write code to sum groups together that would work forever. As soon as an additional key was added, changed, or one completely removed, your code would fail and need to be re-written.

I get the feeling that the data you are receiving is not produced by yourself, but if you can request it is supplied in a usable format, you'll be able to write the code you need. If however you cannot change this, then you'll have to do some string manipulation to place the data items and values into groups you can use - but you will never know what that data really is - they'll just be strings.

As a hack, you could get each item Financial Info object (the key/value pairs), and when passing them through an 'each' function split the key on the underscore and check for your 'curr' and 'prev' values (or pair up the 'bldgs', 'land' etc.), then sum them accordingly. However, I noticed that there is also an 'expl' in one of the keys - this is why any changes may break what you do.

The only way to do this correctly would be to generate a proper JSON object that can tell you what the items are and what values they have. This is the purpose of structured data in models - a string and a value doesn't give you enough to work on.

So a rough example could be:

{
    'Executive Summary': "This is a test. Please ignore.",
    'Financial Info': {
      alt: { curr: "1000", prev: "500"},
      auto: {curr: "2100"},
      bldgs: {curr: "12000", prev: "5000"},
      land: {curr: "30000", prev: "700"},
      machine: {curr: "25000", prev: "1000"},
      other: {curr: "2659", prev: "6000", exp: { curr: "900", expl: "9800", prev: "600"}},
      startup: {curr: "600", prev: "550"},
    },
    ID: 12208
 }

Now you can loop through looking for all items with a 'curr' or 'prev' value, and sum them. Or you can sum the 'curr' and 'prev' for each item in the list. It won't matter what the items names are in the future - you read the name from the JSON object and display its summed values.

So, loop through each item outputting its name and summed values:

Land : "1500" (land.curr, land.prev)

Machine : "26,000" (machine.curr, machine.prev) etc.

Loop through all adding the 'curr', 'prev', and 'expl' as required:

Total Curr: 74,259 (alt.curr, auto.curr, bldgs.curr, land.curr, machine.curr, other.curr, other.exp.curr, and startup.curr)

Total Prev: 14,350 (alt.prev, bldgs.prev, land.prev, machine.prev, other.prev, other.exp.prev, startup.prev)

Total Expl: 9800 (other.exp.expl)

This is only a quick explanation, but you could also change the pure 'objects' above to arrays of 'Items' where each one has a 'Name' and an array of 'Data', each 'Data' item having a 'Type' and a 'Value'.

1 Comment

Actually you can add multiple expression values together. I figured it out. See my accepted answer.
0

OK. So I finally got this working. Thank you to @amirsasson for getting the ball rolling and everyone else here who gave me the info that they did. I really appreciate it.

So you can obviously subtract, divide and multiply expression values by using:

{{ details['Financial Info'].land_curr - details['Financial Info'].land_prev }}

{{ details['Financial Info'].land_curr / details['Financial Info'].land_prev }}

{{ details['Financial Info'].land_curr * details['Financial Info'].land_prev }}

But when I tried to add them as per @amirsasson solution it would not sum up the two values it would just put them side by side.

So What I had to do was multiply the values in the expression by 1 and then add them together like so:

${{ (details['Financial Info'].land_curr * 1 ) + (details['Financial Info'].land_prev * 1) }}

This worked exactly how I needed it to.

Thanks for everyones help.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.