我目前正在开发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(特别是在用那个漂亮的小问题搜索东西写这个问题之前),我来找你。
如果无法做到这一点,我该如何编写ng-options以便获得我想要的行为? (我已经认真尝试了很多,从跟踪到不同的语句和语句,都导致了不同的错误)
在初始加载时,所有选择都显示选择了正确的值,因此所有item.order最初都是INT(我从我们的API获取它们),只有在交互之后,除了触发重新排序的对象之外的所有内容都会搞砸。< / p>
答案 0 :(得分:5)
它变为字符串,因为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;
});
}
};
});
(plunk)
但是我看到有人已经指出可能有更好的方法来跟踪排序。 FWIW该指令至少会确保模型永远不是一个字符串。
答案 1 :(得分:4)
最终我能够通过以下方式解决这个问题:
<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>
这个,只有这个解决方案(到目前为止)有我想要/需要的东西。我需要item.order模型来跟踪当前位置并在初始加载时显示正确的值。你不能将模型设置为questionIndex,因为这扰乱了其他HTML元素,我无法将其设置为$ index,因为这也做了奇怪的事情。
虽然这里提出的其他解决方案“有效”,但它们并不会产生给我的规范。所以我想这有点具体。
答案 2 :(得分:0)
use test;