Javascript AngularJS:ng模型将int切换为string

Javascript AngularJS:ng模型将int切换为string,javascript,angularjs,ng-options,angular-ngmodel,angularjs-ng-options,Javascript,Angularjs,Ng Options,Angular Ngmodel,Angularjs Ng Options,我目前正在Angular中开发一个应用程序。到目前为止,一切都进行得很顺利。我真的,真的是个新手,我很惊讶第一个真正的路障花了这么长时间 情况: 我有一个对象数组,每个对象都有一个顺序 category.items = [{id: 1, order: 1, type: {}, ...}, {id: 54, order: 2, type: {}, ...}, {id: 3, order: 3, type: {}, ...}] 用户需要能够重新排列这些项目。必须将新顺序设置为对象属性“顺序” 在h

我目前正在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中有一个inputfield,键入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>

{{$index+1}}
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();
    }
};
$scope.changeItemOrder=函数(旧订单、新订单、项目索引){
新订单=parseInt(新订单);
if(旧订单!=新订单){
var upper=Math.max(旧订单、新订单);
var lower=Math.min(旧订单、新订单);
角度.forEach($scope.category.items,函数(item,key){
if(项目索引!=键){
if(新订单<旧订单){
如果(项目索引>=新订单和(键+1)>=下订单和(键+1)旧订单){

如果(item_index它被更改为字符串,因为HTML不知道什么是整数。最终,所选变量从DOM中读取并传递给angular,因此它会更改其类型

可以强制模型始终包含带指令的整数

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;
      });
    }
  };
});
()


但我看到有人已经指出,可能有更好的方法来跟踪订单。FWIW该指令至少会确保模型永远不会是字符串。

最终我能够通过以下方式解决这个问题:

<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>

{{$index+1}}
这个,而且只有这个解决方案(到目前为止)有我想要/需要的。我需要item.order模型来跟踪当前位置,并在初始加载时显示正确的值。你不能将模型设置为questionIndex,因为这会干扰其他HTML元素,我不能将它设置为$index,因为这也会造成奇怪的事情


虽然这里建议的其他解决方案“有效”,但它们并没有产生给我的规范。所以我想这有点特殊。

以这种方式跟踪顺序确实是不必要的。从角度上讲,模型是真理的来源。你已经拥有了数据数组-当你在数组中插入/删除项时,你就隐式地重新排序模型。@pixelbits,你是对的,但是,如果我要将空间5的项目切换到空间2,你会怎么做,在插入点拆分数组,将值放在中间,然后再将它们相加?另外,这增加了难度,我需要能够单独保存问题,然后我需要项目。顺序。我可以在运行时将其导出并将其推送到对象,但在执行此操作时,您最好将其保留并在imo中使用。使用arr.splice删除并插入项一旦插入发生,请使用项的新$index同时向服务器发送更新。或者,在最后将整个数组发送回服务器。@pixelbits,好的,我会向powers提出建议,可能会这样解决。我只需要更改服务器端的一些内容就可以了。非常感谢!我已经尝试过了,它在我的情况下不起作用,不知何故它仍然认为我的模型是一个字符串。如果我选择另一个值,该指令会被调用两次。我之前放置了一个日志您的if语句中,1开关的控制台输出为:“string”和“number”。但是select仍然为空,并且添加了一个选项“?string:5”。因此,虽然您的指令确实有效,但最终在创建/更改select时,它会将其读取为字符串……如果这些选项是str,则是字符串的模型,而不是我的选项的值这对于DOM和所有东西都是有意义的……对,我想我没有完全理解您的上下文。每次更改值时,它都会运行两次,因为更改值会触发它再次运行。如果不小心的话,这是一种非常棒的耗尽堆栈的方法。这样的指令仍然会给您控制的能力模型更改时会发生什么情况(使用它的兄弟,
$formatter
可以很好地区分视图和模型)。我想这一次它不是合适的工具。我用这种方法来选择颜色选择器和透明度滑块,因此它可以定义。在某些情况下,如果你想控制值,而不是专门回答这个问题,我很确定你解决了很多其他人通过谷歌出现在这里的问题。(如果发生这种情况)你会惊讶于人们在通过谷歌搜索时经常如此。这是一个很棒的资源,已经帮助了我无数次。顺便说一句,欢迎访问该网站,我很高兴看到你最终找到了解决方案。我在我的项目中也遇到了同样的问题,我只需添加{}就可以解决它围绕我的模型。它解决了我的问题。
.directive('numberToString', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            ngModel.$parsers.push(function (value) {
                return '' + value;
            });
            ngModel.$formatters.push(function (value) {
                return value+'';
            });
        }
    }
});