Javascript Angular.js包含ng重复和过滤器的有限摘要循环
我在angularjs中创建了一个自定义过滤器,它按日期对元素进行分组 这是HTML部分:Javascript Angular.js包含ng重复和过滤器的有限摘要循环,javascript,angularjs,loops,infinite,digest,Javascript,Angularjs,Loops,Infinite,Digest,我在angularjs中创建了一个自定义过滤器,它按日期对元素进行分组 这是HTML部分: <table ng-repeat="(index, groupData) in something = (recentTasks | groupBy:dataGroupBy) track by $index"> 它的作用-输入(recentTasks)是一个任务数组。每个任务都定义了一个“日期”参数。我需要按日期将这些任务分开-每天将在单独的表中。它是有效的,但我得到了无限的摘要循环 你能帮
<table ng-repeat="(index, groupData) in something = (recentTasks | groupBy:dataGroupBy) track by $index">
它的作用-输入(recentTasks)是一个任务数组。每个任务都定义了一个“日期”参数。我需要按日期将这些任务分开-每天将在单独的表中。它是有效的,但我得到了无限的摘要循环
你能帮我解决我的问题吗?还是有更好的解决方案
编辑:
输入和输出示例:
$scope.items = [
{name: 'Abc', date: '2014-03-12'},
{name: 'Def', date: '2014-03-13'},
{name: 'Ghi', date: '2014-03-11'},
{name: 'Jkl', date: '2014-03-12'}
]
输出必须按如下方式分组:
module.filter('groupBy', function () {
return function(items, field) {
var groups = [];
switch (field) {
case 'week':
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateWeeksBack(date);
if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateWeeksBack(date),
tasks: []
};
}
groups[back].tasks.push(item);
groups[back].total_time += item.time;
});
break;
case 'month':
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateMonthsBack(date);
if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateMonthsBack(date),
tasks: []
};
}
groups[back].tasks.push(item);
groups[back].total_time += item.time;
});
break;
default:
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateDaysBack(date);
if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateDaysBack(date),
tasks: []
};
}
groups[back].tasks.push(item);
groups[back].total_time += item.time;
});
}
return groups;
}
});
[
'2013-03-11': [
{name: 'Ghi'}
],
'2013-03-12': [
{name: 'Abc'},
{name: 'Jkl'}
],
'2013-03-13': [
{name: 'Def'}
]
]
$scope.prop1 = Math.random();
$scope.prop2 = Math.random();
$scope.$watch('prop1', function() {
$scope.prop2 = Math.random();
});
$scope.$watch('prop2', function() {
$scope.prop1 = Math.random();
});
因为每天的项目都在HTML结构中的单独表格中
<table ng-repeat="dayData in groupBy(items, 'day')">
<thead>
<tr><td>{{ dayData.date }}</td> </tr>
</thead>
<tbody>
<tr ng-repeat="item in dayData.items">
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>
{{dayData.date}
{{item.name}
要理解为什么会发生这种情况,您需要了解摘要周期。Angular基于“脏检查”,摘要周期是Angular迭代作用域上的所有属性以查看哪些属性已更改。如果任何属性发生了更改,它将触发这些属性的所有监视,以让它们知道发生了什么。由于手表可以改变示波器的属性,Angular会在手表完成后进行另一轮脏检查。当对所有属性进行迭代并且发现它们都没有更改时,摘要循环停止。当手表总是为属性设置新值时,就会出现无限摘要。类似这样的解释可能更好:
$scope.myNumber = Math.random();
$scope.$watch('myNumber', function() {
$scope.myNumber = Math.random();
});
也就是说,我们的手表永远不会停止被调用,因为它总是改变myNumber的值。另一个常见的错误原因是当您有两个属性和两个手表时,如下所示:
module.filter('groupBy', function () {
return function(items, field) {
var groups = [];
switch (field) {
case 'week':
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateWeeksBack(date);
if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateWeeksBack(date),
tasks: []
};
}
groups[back].tasks.push(item);
groups[back].total_time += item.time;
});
break;
case 'month':
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateMonthsBack(date);
if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateMonthsBack(date),
tasks: []
};
}
groups[back].tasks.push(item);
groups[back].total_time += item.time;
});
break;
default:
angular.forEach(items, function(item) {
var parsed = parseDateTime(item.date);
var date = new Date(parsed.year, parsed.month - 1, parsed.day);
var back = calculateDaysBack(date);
if (groups[back] == undefined)
{
groups[back] = {
time_back: calculateDaysBack(date),
tasks: []
};
}
groups[back].tasks.push(item);
groups[back].total_time += item.time;
});
}
return groups;
}
});
[
'2013-03-11': [
{name: 'Ghi'}
],
'2013-03-12': [
{name: 'Abc'},
{name: 'Jkl'}
],
'2013-03-13': [
{name: 'Def'}
]
]
$scope.prop1 = Math.random();
$scope.prop2 = Math.random();
$scope.$watch('prop1', function() {
$scope.prop2 = Math.random();
});
$scope.$watch('prop2', function() {
$scope.prop1 = Math.random();
});
这些手表将以无休止的循环相互触发
因此,在您的情况下,过滤器总是返回一个包含新对象的新数组。Angular不会通过检查所有属性并进行比较来比较对象,相反,它会添加一个$$hashkey
属性,并使用该属性与其他对象进行比较。如果两个对象具有相同的$$hashkey
属性,则认为它们相等。所以,即使每次都返回相同的数据结构,Angular也会将其视为一个新对象,并运行另一个摘要循环,直到它放弃为止
因此,为了使过滤器正常工作,您需要更改代码,以便对于传入的相同参数,它返回一个具有相同对象的数组,如中所示,对这些对象的引用相同。它应该足以确保您不总是为组[返回]创建新对象,而是重用以前的对象
编辑:
好吧,我要让你失望,我建议你重新考虑你的过滤器。对于其他开发人员(或者一年后的您自己)来说,您在ng repeat
上有一个过滤器,它不返回要重复的列表子集,而是一个新的数据结构,这将有点让人困惑。举个例子:
// Controller
$scope.items = [
{name: 'Buy groceries', time: 10},
{name: 'Clean the kitchen', time: 20}
];
// Template
<li ng-repeat="item in items | groupBy:something">
{{item.total_time}}
</li>
这就不那么令人困惑了,因为很明显,
groupBy()
方法返回一个新的数据结构。它还将为您修复无限摘要错误。有两种方法可以解决此问题:
- 老把戏$digest问题-jsfiddle.net/LE6Ay
- 添加了$$hashKey属性-jsfiddle.net/LE6Ay/1
<div ng-init="issues=myCtrl.getUniqueIssues()">
<div ng-repeat="issue in issues">{{issue.name}}</div>
</div>
{{issue.name}
我的资料来源还有一个过滤器示例:感谢您的解释,现在我明白了为什么会出现错误。但我仍然不知道,如何解决它。你能多帮我一点忙吗?谢谢转发!非常感谢你的回答!实际上,我真的不知道如何在不改变结构的情况下做到这一点。问题是,在我的输入中(“项”)是未排序的任务。在输出中,我需要对任务进行排序和分组。我已经在我的第一篇文章中添加了一些示例。你现在能帮我找到解决办法吗?