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