AngularJS - 获取多个JSON键值并将它们相加

4

这是我的Angular代码:

  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;
    });
  }

这是我正在处理的JSON数据的图片:

enter image description here

如您所见,在“财务信息”下面,我有多个具有货币值的键。如何在Angular中提取这些值并将它们相加,然后在我的HTML文件中显示该结果。

我显然可以通过使用以下方法在html中获取land_curr和land_prev值:

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

但是在我得到的HTML中,有一个“总金额”的位置。因此,我需要将这些值相加,然后将这个新值放入HTML文件中的“总金额”部分。

我能做到吗?

编辑:

请注意,这些JSON值将会更改,因此我不能将货币值“硬编码”到任何内容中,因为货币金额经常会更改。而且我需要能够将所有“_prev”值相加和所有“_curr”值相加。而且我只需要能够将“land_curr”和“land_prev”相加。

5个回答

2

由于JS是一种动态语言,您可以向“财务信息”添加一个执行数学运算的新属性/方法,例如:

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

您可以直接在您的HTML中编写。
{{ details['Financial Info'].land_curr + details['Financial Info'].land_prev}}

如果可能的话


{{ details['Financial Info'].land_curr + details['Financial Info'].land_prev }} ...只是将这些值放在一起。我需要将它们相加。就你展示的第一个选项而言,我应该放在哪里,然后如何将其提取到我的 HTML 文件中呢? - agon024
1
感谢您为我提供解决方案的起点。基于您的起点,我已经找到了答案。请查看我的采纳答案。 - agon024

2
我建议从html中调用一个函数来获取总数。这样,如果“财务信息”对象中的值动态更改,总和也将更新。请参见我提供的示例(我还加入了一个ng-repeat来列出所有的“财务信息”,以及currency过滤器,以防您不知道它们)。
在示例中,我只是将您的示例对象硬编码到$scope.details变量中。在实际应用程序中,您仍然可以像以前一样填充它 - 使用$http服务调用您的API。
您可以在控制器的$scope中添加一个名为getTotal()的函数。这样,您可以直接从html中使用{{getTotal()}}调用它。
getTotal()方法中,您只需要利用angular内置的forEach()方法(或者如果您喜欢的话,只是普通的纯javascript)来循环遍历“金融信息”对象中的每个项目。然后,您只需要调用parseInt()传递值,因为它们是您对象中的字符串,然后将其添加到一个运行中的sum变量中。最后,在angular的forEach()完成后,您可以返回sum
编辑:添加了获取所有_curr值和_prev值以及land_的总数的方法。
编辑2:添加了一个超时,以模拟通过您的$http调用加载数据。为了避免在您的$http调用返回之前出现$scope.details为空的错误,您可以在每个getTotal函数的开头添加if(!$scope.details){return;} ,或者您可以将$scope.details初始化为您期望您的$http调用返回的每个项目的null或空值。例如,在下面的代码片段中,我将$scope.details变量初始化如下:
$scope.details = {
  'Executive Summary': null,
  'Financial Info': {},
  ID: null
};

示例:

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>


1
啊,没事了,我现在看到它正在循环遍历一个对象,是我的错。 - demux
所以我在"$scope.details = data;"下面添加了代码,并将其添加到我的HTML中,我可以列出所有键和值,但无法获取总数。此外,我需要能够将所有"_prev"值加在一起和"_curr"值加在一起。我还需要能够将"land_curr"和"land_prev"之类的内容相加。 - agon024
请查看我的最新编辑,了解如何对prevcurrland等值进行求和。 - Andrew Mairose
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Andrew Mairose
您可以将此代码添加到每个函数的开头,这样如果在加载数据之前调用它们就不会出错。if (!scope.details){ return; } - Andrew Mairose
显示剩余7条评论

0
你在 Angular 中尝试使用 forEach 了吗?请看下面的示例:
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)
         }]);

编辑: 在你的HTML中,你可以像下面展示变量:

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

你是不是想说 vm.sum += parseInt(val); - Andrew Mairose
编辑了。命名规范问题。那是val,key对(1000,alt_curr)。 - Naveen
JSON值取决于所访问的“汽车”,并且可以随时更改。如果我理解得正确,您已经为“alt_curr”赋了一个特定的值。我需要从JSON键中提取值,然后将它们相加。因此,1000和2000将随时间而变化。 - agon024
没问题,当您迭代“财务信息”对象时,您将读取所有动态值。我只是为了让您理解而创建了一个对象 :) - Naveen

0

很遗憾,如果您的列表中的键可以随时更改,那么您永远无法编写代码来对组进行求和,这将永远不会失效。一旦添加了额外的键、更改或完全删除了一个键,您的代码就会失败并需要重新编写。

我感觉您收到的数据不是由您自己生成的,但如果您可以请求以可用格式提供它,您将能够编写所需的代码。但是,如果您无法更改此内容,则必须进行一些字符串操作,以将数据项和值放入您可以使用的组中-但您永远不会知道那些数据实际上是什么-它们只是字符串。

作为一种hack方法,您可以获取每个项目的财务信息对象(键/值对),并在通过“each”函数传递它们时拆分键并检查您的“curr”和“prev”值(或配对“bldgs”,“land”等),然后相应地对它们进行求和。但是,我注意到其中一个键中还有一个“expl”-这就是为什么任何更改都可能破坏您的操作。

唯一正确的方法是生成一个适当的JSON对象,可以告诉您项目是什么以及它们具有什么值。这就是模型中结构化数据的目的 - 仅有字符串和值无法为您提供足够的工作依据。
因此,一个粗略的示例可能是:
{
    '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
 }

现在您可以循环查找所有具有“curr”或“prev”值的项目,并对它们求和。 或者您可以为列表中的每个项目汇总“curr”和“prev”。 将来项目名称无论是什么都不重要 - 您从JSON对象中读取名称并显示其求和值。
因此,循环遍历每个项目,输出其名称和总和值:
土地:“1500”(land.curr,land.prev)
机器:“26,000”(machine.curr,machine.prev)等
循环遍历所有内容,根据需要添加“curr”,“prev”和“expl”:
总计Curr:74,259(alt.curr,auto.curr,bldgs.curr,land.curr,machine.curr,other.curr,other.exp.curr和startup.curr)
总计Prev:14,350(alt.prev,bldgs.prev,land.prev,machine.prev,other.prev,other.exp.prev和startup.prev)
总计Expl:9800(other.exp.expl)
这只是一个快速的解释,但您还可以将纯“对象”更改为“Items”的数组,其中每个条目都有一个“Name”和一个“Data”数组,每个“Data”项都有一个“Type”和一个“Value”。

1
实际上,您可以将多个表达式值相加。我已经弄清楚了。请查看我的被接受的答案。 - agon024

0
好的。所以我终于搞定了。感谢@amirsasson的启动和其他在这里给我提供信息的人。我非常感激。
显然,你可以通过以下方式对表达式值进行减法、除法和乘法运算:
{{ 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 }}

但是当我尝试按照@amirsasson的解决方案添加它们时,它不会将两个值相加,而只会将它们并排放置。

所以我必须在表达式中将这些值乘以1,然后将它们相加,就像这样:

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

这正是我所需要的。

感谢大家的帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接