Javascript 在AngularJS应用程序中使用Lo Dash从REST返回求和

Javascript 在AngularJS应用程序中使用Lo Dash从REST返回求和,javascript,arrays,angularjs,object,lodash,Javascript,Arrays,Angularjs,Object,Lodash,向下滚动以获取解决方案 我有一个简单的AngularJS应用程序(在angular.js之后、app.js之前加载lodash): 项目列表页(/projects),其中项目上的链接将其带到/projects/:id 在/projects/:id中,控制器对API执行get请求,并返回数据 我将数据分配给$scope.project,并在视图中显示它 以下是我从API获得的回报示例: { "_id" : { "$oid" : "546a3bdee4b0bfd97138fe08"}

向下滚动以获取解决方案

我有一个简单的AngularJS应用程序(在angular.js之后、app.js之前加载lodash):

  • 项目列表页(/projects),其中项目上的链接将其带到/projects/:id
  • 在/projects/:id中,控制器对API执行get请求,并返回数据
  • 我将数据分配给$scope.project,并在视图中显示它
以下是我从API获得的回报示例:

{ 
    "_id" : { "$oid" : "546a3bdee4b0bfd97138fe08"} , 
    "picture" : "http://placehold.it/400x400" , 
    "name" : "Square Campus" ,  
    "address" : "293 Grafton Street, Shasta, Arizona, 6757" , 
    "phone" : "+1 (916) 544-2274" , 
    "buildings" : [ 
        { "name" : "North Campus" , "floors" : "4" , "users" : "8"} , 
        { "name" : "South Campus" , "floors" : "2" , "users" : "15"} , 
        { "name" : "East Wing" , "floors" : "8" , "users" : "23"}
    ]
}

// Using this call in the controller
$scope.project = Restangular.one('projects', $routeParams.projectId).get().$object;
        <aside class="aside-primary col-xs-12 col-md-3">
            <div class="well">
                <img ng-src="{{project.picture}}" alt="" class="img-responsive"/>
                <strong>{{project.name}}</strong><br />
                {{project.address}}<br />
                {{project.phone}}<br />
            </div>
        </aside>

        <section class="primary-content col-xs-12 col-md-9">
            <h1>{{project.name}}</h1>

            <h2>Buildings</h2>
            <table class="table table-hover table-bordered">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Floors</th>
                        <th>Users</th>
                    </tr>
                </thead>
                <tbody>
                    <tr data-ng-repeat="building in project.buildings">
                        <td>{{building.name}}</td>
                        <td>{{building.floors}}</td>
                        <td>{{building.users}}</td>
                    </tr>
                    <tr>
                        <td><strong>Total</strong></td>
                        <td></td>
                        <td></td>
                    </tr>
                </tbody>
            </table>

        </section>
下面是我在视图中显示它的方式:

{ 
    "_id" : { "$oid" : "546a3bdee4b0bfd97138fe08"} , 
    "picture" : "http://placehold.it/400x400" , 
    "name" : "Square Campus" ,  
    "address" : "293 Grafton Street, Shasta, Arizona, 6757" , 
    "phone" : "+1 (916) 544-2274" , 
    "buildings" : [ 
        { "name" : "North Campus" , "floors" : "4" , "users" : "8"} , 
        { "name" : "South Campus" , "floors" : "2" , "users" : "15"} , 
        { "name" : "East Wing" , "floors" : "8" , "users" : "23"}
    ]
}

// Using this call in the controller
$scope.project = Restangular.one('projects', $routeParams.projectId).get().$object;
        <aside class="aside-primary col-xs-12 col-md-3">
            <div class="well">
                <img ng-src="{{project.picture}}" alt="" class="img-responsive"/>
                <strong>{{project.name}}</strong><br />
                {{project.address}}<br />
                {{project.phone}}<br />
            </div>
        </aside>

        <section class="primary-content col-xs-12 col-md-9">
            <h1>{{project.name}}</h1>

            <h2>Buildings</h2>
            <table class="table table-hover table-bordered">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Floors</th>
                        <th>Users</th>
                    </tr>
                </thead>
                <tbody>
                    <tr data-ng-repeat="building in project.buildings">
                        <td>{{building.name}}</td>
                        <td>{{building.floors}}</td>
                        <td>{{building.users}}</td>
                    </tr>
                    <tr>
                        <td><strong>Total</strong></td>
                        <td></td>
                        <td></td>
                    </tr>
                </tbody>
            </table>

        </section>

有人能帮我弄清楚吗

谢谢大家!

解决方案

重要的是,在进行Restangular调用时,定义“then”承诺,因为数据最初不是在初始页面加载时加载的

    var detailProject = Restangular.one('projects', $routeParams.projectId);
    detailProject.get().then(function (project) {
        $scope.project = project;    // Assign the owner to a model

        var sums = _.reduce(project.buildings,
          function (sums, building) {
              return {
                  floors: sums.floors + parseInt(building.floors),
                  users: sums.users + parseInt(building.users)
              };
          },
          { floors: 0, users: 0 } // initial values
        );
        console.log(sums);
    });

这样的办法应该行得通

$project.totalFloors = _.reduce($project.buildings, function(s, entry) {
    return s + parseFloat(entry.floors);
}, 0);

$project.totalUsers = _.reduce($project.buildings, function(s, entry) {
    return s + parseFloat(entry.users);
}, 0);

如果要同时计算楼层和用户,而不是对数据进行两次迭代,可以这样做:

var sums = _.reduce( $scope.project.buildings,
  function(sums, building) {
    return { floors: sums.floors + parseInt(building.floors),
             users:  sums.users + parseInt(building.users) };
  },
  { floors: 0, users: 0 } // initial values
);

console.log(sums);
// => { floors: 14,
//      users: 46 }
您可以将其分配给
$scope.project
对象上的属性,以便在视图中显示:

$scope.project.buildingTotals = _.reduce( $scope.project.buildings, // ...
……然后

<tr>
    <td><strong>Total</strong></td>
    <td>{{project.buildingTotals.floors}}</td>
    <td>{{project.buildingTotals.users}}</td>
</tr>

总计
{{project.buildingTotals.floors}
{{project.buildingTotals.users}}

试试这个。首先使用Pulk仅获取楼层值,然后在此基础上使用reduce

只需稍加修改就可以计算用户数量。需要parseInt,因为您的数字是字符串,所以使用plus将连接它们,而不是在没有它的情况下添加它们

var sumFloors = _.pluck(project['buildings'], 'floors').reduce(function(previous, current){
    return parseInt(previous, 10) + parseInt(current, 10);
});

您在这里使用$project而不是$scope.project(就像我在重新启动时定义的那样)有什么具体原因吗。在我的例子中,当jshint试图验证我的控制器app\scripts\controllers\project-detail.js第18行第33列“$project”未定义时,我遇到了这个错误。@eHx:no,只是键入错误。很抱歉造成混淆。为什么我在尝试控制台日志时会得到初始值?对象{楼层:0,用户:0}。我还尝试了console.log(sums.floors);我仍然得到0。。。有什么想法吗?想出来了。。。将在原始帖子中发布解决方案我不知道为什么会发生这种情况,但我确实发现我编写的视图代码存在问题,而不是,例如,
{{buildingTotals.floors}
它应该是
{{project.buildingTotals.floors}
。我已经更新了我的答案,并在这里创建了一个有效的JSFIDLE:为什么要在这里使用
lodash
@Jordan的解决方案很好,但每次迭代都会创建一个新对象。从性能的角度看不太好。我建议对这种琐碎的任务使用简单的
for
循环。@Kiril在看到对象创建开销的任何实际影响之前,您需要数千条记录。无论如何,如果您想避免这种开销,您可以更新
sums
对象的属性并返回它,而不是每次创建一个新对象()。