Javascript 使用ng repeat填充表并检查匹配的标题数据

Javascript 使用ng repeat填充表并检查匹配的标题数据,javascript,angularjs,Javascript,Angularjs,我有一个用于填充表格标题行的年份数组,还有一个用于填充表格的对象。 我需要在相应的年份标题下填充正确的年份数据,因此我需要检查对象中的年份(Y)是否对应于标题数组中的年份,如果不对应,则需要添加一个空单元格。对象按年份排序。最好的方法是什么? 这是你的电话号码 控制器 var app = angular.module("testModule", []); app.controller('testController', function($scope) { $scope.headerYea

我有一个用于填充表格标题行的年份数组,还有一个用于填充表格的对象。 我需要在相应的年份标题下填充正确的年份数据,因此我需要检查对象中的年份(Y)是否对应于标题数组中的年份,如果不对应,则需要添加一个空单元格。对象按年份排序。最好的方法是什么? 这是你的电话号码

控制器

 var app = angular.module("testModule", []);
 app.controller('testController', function($scope) {
 $scope.headerYears = [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020];

$scope.rows = [{
  "Name": "Name1",
  "Col": [{
    "Y": 2013,
    "M": 25711
  }, {
    "Y": 2014,
    "M": 26095
  }, {
    "Y": 2015,
    "M": 23641
  }, {
    "Y": 2016,
    "M": 22224
  }, {
    "Y": 2017,
    "M": 21968
  }, {
    "Y": 2018,
    "M": 23820
  }, {
    "Y": 2019,
    "M": 26673
  }, {
    "Y": 2020,
    "M": 29329.5
  }]
}, {
  "Name": "Name2",
  "Col": [{
    "Y": 2013,
    "M": 83
  }, {
    "Y": 2014,
    "M": 461
  }, {
    "Y": 2015,
    "M": 1067
  }, {
    "Y": 2016,
    "M": 1120
  }, {
    "Y": 2017,
    "M": 1050
  }, {
    "Y": 2018,
    "M": 600
  }, {
    "Y": 2019,
    "M": 475
  }, {
    "Y": 2020,
    "M": 481
  }]
}, {
  "Name": "Name3",
  "Col": [{
    "Y": 2013,
    "M": 25794
  }, {
    "Y": 2014,
    "M": 26556
  }, {
    "Y": 2015,
    "M": 24708
  }, {
    "Y": 2016,
    "M": 23424
  }, {
    "Y": 2017,
    "M": 23297
  }, {
    "Y": 2018,
    "M": 24412.5
  }, {
    "Y": 2019,
    "M": 27090.5
  }, {
    "Y": 2020,
    "M": 29754.5
  }]
 }]
});
HTML


{{i}
{{item.M}{{item.Y}

如果在DOM中,我会执行ng

<table border="1" data-ng-app="testModule" data-ng-controller="testController">
  <thead>
    <tr>
      <th ng-repeat="i in headerYears">{{i}}</th>
    </tr>
  </thead>
  <tbody>
    <tr >
      <td ng-repeat="i in headerYears" >{{i}}  
      <span ng-repeat="row in rows"></span> 
      <span ng-repeat="item in row.Col">{{item.Y}} </span>
      </td>     
    </tr>
  </tbody>
</table>

{{i}
{{i}
{{item.Y}

编辑:您可以向span中添加一个NG-IF,如span NG IF=“item.Y==i”和另一个span NG IF=“item.Y!=i”

,因为row.col的长度可以小于、大于或等于headerYears长度,您必须确保表中的列具有一致性

这意味着对于每一行,您必须在headerYears上重新复制以创建相同的列大小

看一看我创建的解决方案,它可能会为您提供解决方案

另外,创建一个绑定到控制器中提供的年份的新对象数组,然后重复到这个新数组也是一个好主意

Imho这将提供一个更干净的DOM,并且可以更容易地进行维护

我添加了一个过滤器,以便读取列数据并返回适合每种情况的数据

 app.filter('testFilter', function() {
    return function(col, header) {
       if (!col ){
        return "Empty";
       } 
       if (!header){
        return "Empty"; 
       }


       var returnVal="Empty Item";
       angular.forEach(col, function(colItem){
         if(header===colItem.Y) {
            returnVal = colItem.M+" "+colItem.Y;
        }
       });

    return returnVal;

   }
});
我还更改了DOM,现在它看起来如下所示

<tbody>
   <tr ng-repeat="row in rows">
      <td ng-repeat="i in headerYears">
         {{row.Col | testFilter:i }}
      </td>
   </tr>
</tbody>

{{row.Col | testFilter:i}

这很有效,比为每个要显示的值构建自定义过滤器要好(即,您可以将任何想要的HTML放在TD中,只需像正常情况一样使用{item.myProperty}})。享受吧

它将您的所有数据转换为与标题匹配的格式,让JS做它最擅长的事情,然后将干净的数据提供给Angular。希望有帮助

//START OF GOOD CODE
$scope.rows = null;

(function(){
  var raw = [{ /** this is all your current "rows" data, just moved**/ }];

  var bucketize = function(col) {
      var data = new Array();
      for (var i = 0; i < $scope.headerYears.length; i++) {
          data.push({}); //initialize to match headerYears setup
          for (var j = 0; j < col.length; j++) {
              if (col[j].Y == $scope.headerYears[i]) {
                  data[i] = col[j]; //replace initialized value with real data
              }
          }
      }
      return data;
  };

  var rows = new Array();

  for (var x = 0; x < raw.length; x++) {
    var row = raw[x];
    row.Col = bucketize(row.Col); //sort data and format it for our desired HTML        
    rows.push(row);
  }

  $scope.rows = rows; //give the scrubbed data to Angular
})();
//END OF GOOD CODE
//好代码的开始
$scope.rows=null;
(功能(){
var raw=[{/**这是您当前所有的“行”数据,刚刚移动**/}];
var bucketize=函数(col){
var data=新数组();
对于(变量i=0;i<$scope.headerYears.length;i++){
data.push({});//初始化以匹配headerYears设置
对于(变量j=0;j
--编辑--

下面创建了一个无限摘要循环,因为它在每次调用bucketize()函数时都返回一个新数组()。相反,在将数据提供给Angular之前,请先对其进行清理(请参见上文)。您可以在AJAX成功处理程序中实现这一点,甚至可以像上面那样使用sef

//NOTE THIS IS BAD, DUE TO INFINITE LOOP CAUSED BY "new Array();"
...
<td ng-repeat="item in bucketize(row.Col)">{{item.Y}}</td>
...
$scope.bucketize = function(col) {
    var data = new Array();
    for (var i = 0; i < $scope.headerYears.length; i++) {
        data.push({}); //initialize to match headerYears setup
        for (var j = 0; j < col.length; j++) {
            if (col[j].Y == $scope.headerYears[i]) {
                data[i] = col[j]; //replace initialized value with real data
            }
        }
    }
    return data;
};
//END OF BAD CODE
//注意这是错误的,因为“new Array();”导致无限循环
...
{{item.Y}
...
$scope.bucketize=函数(列){
var data=新数组();
对于(变量i=0;i<$scope.headerYears.length;i++){
data.push({});//初始化以匹配headerYears设置
对于(变量j=0;j
  • 基隆

根据我的说法,您应该编写应用程序逻辑代码,比如根据
headerYears
同步所有
行Col
数据。我甚至只需在第一个for()循环中使用“data=new Array();…for…data.push({});…”来构建数据,以确保它始终与头完全匹配(如果头是变量的话)。。。但无论如何。就像我说的,希望这有帮助!它确实可以工作,但不幸的是在浏览器中返回错误。很好的捕获!我没有看控制台,只是看HTML输出。这是因为每次迭代都返回一个名为“data”的新对象,该对象随后会触发一组全新的摘要。我更新了代码以在Angular之外工作。我仍然强烈推荐这种方法——它基本上做了与您接受的答案相同的事情,但它依赖于JS使JS数据正确——并且依赖Angular使HTML与JS数据匹配——这正是每个人应该做的。这似乎是目前为止最合适的答案。但是,如果我想在colItem中显示更多的属性,并且我想对它们进行不同的样式设置,或者将它们打开或关闭,那么我需要像colItem.McolItem.Y这样的东西。。。如果我从过滤器返回整个对象,例如returnVal=colItem;如何在DOM中访问它?我希望我的问题有道理是的你的问题有道理。由于您希望能够控制在标记中自定义DOM,如果我是您,我会在整个对象上为该作业创建一个单独作用域的指令responsible,并按如下所示使用它。您可以始终使用该指令的templateUrl功能,以便清楚地了解正在发生的事情。通过这种方式,您还可以为每个单元格添加一些功能,如CRUD Opperations这是最简单的,允许我在之后修改输出。我不确定使用这种方法会导致什么样的失败。。
//NOTE THIS IS BAD, DUE TO INFINITE LOOP CAUSED BY "new Array();"
...
<td ng-repeat="item in bucketize(row.Col)">{{item.Y}}</td>
...
$scope.bucketize = function(col) {
    var data = new Array();
    for (var i = 0; i < $scope.headerYears.length; i++) {
        data.push({}); //initialize to match headerYears setup
        for (var j = 0; j < col.length; j++) {
            if (col[j].Y == $scope.headerYears[i]) {
                data[i] = col[j]; //replace initialized value with real data
            }
        }
    }
    return data;
};
//END OF BAD CODE