带过滤器的AngularJS表

时间:2014-11-13 15:56:11

标签: angularjs angularjs-directive angularjs-ng-repeat

我得到一个像下面这样的对象:

$scope.Students = [{
    "Name": "Muffin 1",
    "RollNo": "12312",
    "Class": "Standard B",
    "Performances": [{
      "Group": "Science",
      "Subject": "Math",
      "Mark": 99
    }, {
      "Group": "Science",
      "Subject": "Physics",
      "Mark": 99
    }, {
      "Group": "Arts",
      "Subject": "Drawing",
      "Mark": 99
    }, {
      "Group": "Arts",
      "Subject": "Poetry",
      "Mark": 99
    }]
  }, {
    "Name": "Muffin 2",
    "RollNo": "1232",
    "Class": "Standard A",
    "Performances": [{
      "Group": "Science",
      "Subject": "Chemistry",
      "Mark": 99
    }, {
      "Group": "Science",
      "Subject": "Physics",
      "Mark": 90
    }, {
      "Group": "Arts",
      "Subject": "Drawing",
      "Mark": 99
    },  {
      "Group": "Commerce",
      "Subject": "Marketing",
      "Mark": 99
    }]
  }];

我想创建一个这样的表:

enter image description here

Performances.Group的固定已知值是:科学,艺术或商业但SubjectMark始终是可变的。所以我要做的是将所有主题名称放在左栏中,然后如果学生有该主题的标记,则将其放在学生专栏中。任何人都可以帮我解决这个问题!这是Plunker链接:http://plnkr.co/edit/vvLL00crhwSq4I6pjjUx?p=preview

虽然,我可以按群组过滤所有的表演,但后来我很困惑如何在左栏中包含所有主题名称,然后相应的值,因为它们在单独的数组中。

2 个答案:

答案 0 :(得分:1)

首先,您必须在易于模板的结构中重构数据(plunker):

var rows = [[],[],[]]

rows[0].title = 'Student Name';
rows[1].title = 'Roll No';
rows[2].title = 'Class';

var groups = {};
var cols = $scope.Students.length;

angular.forEach($scope.Students , function(student, idx){

  rows[0].push(student.Name);
  rows[1].push(student.RollNo);
  rows[2].push(student.Class);

  angular.forEach(student.Performances , function(p) {

    // collect groups
    groups[p.Group] = groups[p.Group] || {};

    // collect subjects per group
    groups[p.Group][p.Subject] = groups[p.Group][p.Subject] || Array(cols);

    // collect marks per each group subject
    groups[p.Group][p.Subject][idx] = p.Mark;
  });
});

$scope.rows = rows;
$scope.groups = groups;

然后您可以轻松地迭代这些项目:

  <table class="table table-bordered">
    <tr ng-repeat="row in rows">
      <th>{{row.title}}</th>
      <th ng-repeat="cell in row track by $index">{{cell}}</th>
    </tr>

    <tbody ng-repeat="(group, sections) in groups">
      <tr>
        <th>Group</th>
        <th colspan={{Students.length}}>{{group}}</th>
      </tr>
      <tr ng-repeat="(section, values) in sections">
        <th>{{section}}</th>
        <th ng-repeat="value in values track by $index">{{value}}</th>
      </tr>
    </tbody>
  </table>

答案 1 :(得分:1)

这非常符合您的需求:

http://plnkr.co/edit/mvSvBCSowmdKFmprSvBo?p=preview

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $filter) {
  ...

  $scope.studentsFiltered = $filter('groupByCustom')($scope.Students);
  console.log('restructured', $scope.studentsFiltered); 

});

现在你想要一种以可重用的方式重组数据的方法,我认为过滤器做得很好。

app.filter('groupByCustom', function(){
  return function(studentsList){
    console.log('studentsList', studentsList);
    // given a list of students, group into classes
    // final structure should be object which contains a different nesting
    /* we want:
       var grouping = {
         Science: {
           Math: {muffin 1: 99, muffin 2: 99},
           Chemistry: {muffin 1: 99, muffin 2: 99}
           // null if student is not in class
         }
       }
    */
    var newStructure = {};
    angular.forEach(studentsList, function(student, index){
      var name = student.Name;
      var performances = student.Performances;
      angular.forEach(performances, function(perf, ind){
        var group = perf.Group;
        var mark = perf.Mark;
        var sub = perf.Subject;

        if(!newStructure[group]){
          newStructure[group] = {};
        }
        if(!newStructure[group][sub]){
          newStructure[group][sub] = {};
          angular.forEach(studentsList, function(student, index){
            if(!newStructure[group][sub][student.name]){
              newStructure[group][sub][student.Name] = null;
            }
          });
        }
        if(!newStructure[group][sub][name]){
          newStructure[group][sub][name] = mark; 
        }
      });
    });
    angular.forEach(newStructure, function(k,v){
      angular.forEach(v, function(k,v){

      });
    });

    // console.log('newStructure', newStructure);
    return newStructure;
  };
});

然后你可以构建HTML:

<tbody ng-repeat="(group, data) in studentsFiltered">
  <tr >
    <th class="section">Group</th>
    <th class="section" colspan={{Students.length}}>{{group}}</th>
  </tr>
  <tr ng-repeat="(class, students) in data">
    <td>{{class}}</td> 
    <td ng-repeat="(name, score) in students">{{score}}</td>
  </tr>
</tbody>