我目前正在开发Angular中的应用程序。到目前为止,一切都很顺利。对于棱角分明,我真的非常非常新,我很惊讶第一个真正的障碍花了这么长时间。
情况:
我有一个对象数组,每个对象都有一个订单。
category.items = [{id: 1, order: 1, type: {}, ...}, {id: 54, order: 2, type: {}, ...}, {id: 3, order: 3, type: {}, ...}]
用户需要能够重新排列这些项目。必须将新订单设置为对象属性“订单”。
在html中,这些对象的呈现方式如下:
<div class="category">
<div class="item" ng-repeat="(itemIndex, item) in category.items track by $index">
<div class="header">
</div>
</div>
</div>
在header-div中我有一个输入字段,类型为select。
<select ng-model="item.order" ng-change="changeItemOrder((itemIndex + 1), item.order, itemIndex)">
<option ng-repeat="item in category.items" ng-value="($index + 1)">{{$index + 1}}</option>
</select>
changeItemOrder的代码:
$scope.changeItemOrder = function(old_order, new_order, item_index) {
new_order = parseInt(new_order);
if (old_order != new_order) {
var upper = Math.max(old_order, new_order);
var lower = Math.min(old_order, new_order);
angular.forEach($scope.category.items, function(item, key) {
if (item_index != key) {
if (new_order < old_order) {
if (item_index >= new_order && (key + 1) >= lower && (key + 1) <= upper) {
item.order = (parseInt(item.order) + 1);
}
} else if (new_order > old_order) {
if (item_index <= old_order && (key + 1) <= upper && (key + 1) >= lower) {
item.order = (parseInt(item.order) - 1);
}
}
} else {
item.order = parseInt(new_order);
}
});
$scope.reorderItems();
}
};
(ReorderItems只使用默认排序机制调用角度排序,比较顺序并返回-1,1或0)
这是我在这个问题的可能解决方案之一中发现/发现/查明其中一个突破性错误的地方。在这里,我注意到我的INT以某种方式转换为字符串,因为在渲染时,选项被添加到值为'string:2'的下拉列表中。
我已经以各种可能的方式尝试过ng-options,但即便是那些也导致了问题。我做ng-options的方式是将item.order作为item.order在...等等,只是让订单切换到某种程度上所有项目都有相同的顺序。尝试不同的分组方法或trackbys只会给出不同的错误,例如在下拉列表中突然引入NaN en NULL,或者从item-object中完全删除order属性。
到目前为止,最少有错误的解决方案一直在我的选项上使用ng-repeat。这只会导致item.order类型不匹配。
现在,经过广泛的搜索,花费数小时的stackoverflow(特别是在用那个漂亮的小问题搜索东西写这个问题之前)我来找你。
它被更改为字符串,因为HTML没有整数是什么的概念。最终,从DOM读取所选变量并将其传递给角度,因此它会改变其类型。
您可以强制模型始终包含带指令的整数
directive('forceInt', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, controller) {
controller.$parsers.push(function(value) {
if (typeof value === 'string') {
value = parseInt(value, 10);
controller.$setViewValue(value);
controller.$render();
}
return value;
});
}
};
});
(Qazxswpoi)
但是我看到有人已经指出可能有更好的方法来跟踪排序。 FWIW该指令至少会确保模型永远不是一个字符串。
最终我通过这样做来解决这个问题:
plunk
这个,只有这个解决方案(到目前为止)有我想要/需要的东西。我需要item.order模型来跟踪当前位置并在初始加载时显示正确的值。你不能将模型设置为questionIndex,因为这扰乱了其他HTML元素,我无法将其设置为$ index,因为这也做了奇怪的事情。
虽然其他解决方案在这里建议“工作”,但它们不会产生给我的规范。所以我想这有点具体。
<div class='header'>
<select ng-model="item.order" ng-change="changeItemOrder((itemIndex + 1), item.order, itemIndex)">
<option ng-repeat="thing in category.items" ng-selected="(item.order === ($index + 1))" value="{{$index + 1}}">{{$index + 1}}</option>
</select>
</div>