javascript AngularJS:ng-model 将 int 转换为字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24826608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 03:23:58  来源:igfitidea点击:

AngularJS: ng-model switching int to string

javascriptangularjsng-optionsangular-ngmodelangularjs-ng-options

提问by thisisboris

I'm currently working on an app in Angular. So far, everything has been going -quite- well. I'm really, reallynew to angular and am amazed that it took so long for the first real roadblock.

我目前正在 Angular 中开发一个应用程序。到目前为止,一切都进展顺利。我对 angular真的非常陌生,我很惊讶第一个真正的障碍花了这么长时间。

Situation:

情况:

I have an array of objects each with an order.

我有一个对象数组,每个对象都有一个订单。

category.items = [{id: 1, order: 1, type: {}, ...}, {id: 54, order: 2, type: {}, ...}, {id: 3, order: 3, type: {}, ...}]

The user needs to be able to rearrange these items. The new order must be set to the object property 'order'.

用户需要能够重新排列这些项目。新订单必须设置为对象属性“订单”。

In html these objects are rendered like so:

在 html 中,这些对象的呈现方式如下:

<div class="category">
    <div class="item" ng-repeat="(itemIndex, item) in category.items track by $index">
        <div class="header">
        </div>
    </div>
</div>

In the header-div I have an inputfield, type select.

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

The code for changeItemOrder:

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 just call angular sorting with a default sorting mechanism comparing the orders and returning -1, 1 or 0.)

(ReorderItems 只是使用默认排序机制调用角度排序,比较订单并返回 -1、1 或 0。)

Here is where I discovered/spotted/pinpointed one of the breaking bugs in one of the possible solutions for this problem. Here I noticed that my INT is converted to string somehow, as on render an option is added to the dropdown with value 'string:2'.

这是我在此问题的可能解决方案之一中发现/发现/查明其中一个重大错误的地方。在这里,我注意到我的 INT 以某种方式转换为字符串,因为在渲染时,下拉列表中添加了一个值为“string:2”的选项。

I've tried ng-options, in all possible ways, but even those led to problems. The way I did ng-options was by doing item.order as item.order in ... and so on, that just made the order switch around until somehow all items had the same order. Trying different grouping methods or trackbys just gave different bugs, like suddenly introducing NaN en NULL in the dropdown, or completely removing the order property as a whole from the item-object.

我已经以所有可能的方式尝试过 ng-options,但即使是那些也会导致问题。我做 ng-options 的方法是将 item.order 作为 item.order in ... 等等,这只是使订单切换,直到不知何故所有项目都有相同的订单。尝试不同的分组方法或 trackbys 只会产生不同的错误,例如突然在下拉列表中引入 NaN en NULL,或者从 item-object 中完全删除 order 属性作为一个整体。

So far the least bug-ridden solution has been using the ng-repeat on my options. That only causes a mismatch on the type of item.order.

到目前为止,漏洞最少的解决方案是在我的选项中使用 ng-repeat。这只会导致 item.order 的类型不匹配。

Now, after searching far and wide, spending hours on stackoverflow (especially before writing up this question with that nifty little question-searching thingy) I come to you.

现在,经过广泛的搜索,在 stackoverflow 上花费数小时(尤其是在用那个漂亮的小问题搜索工具写下这个问题之前)我来找你了。

  1. How can I halt/circumvent the behavior where my item.order is switched from INT to STRING?
  2. If that isn't possible, how can I force my $index to be a string, so the model(string) matches the value(string)
  3. If that isn't possible, how can I write my ng-options so that I get the behavior I want? ( I've seriously tried a lot, from track by to different as and for statements, all resulted in different bugs)

    On initial load, all selects show a correct value selected, so all item.order are initially INT (I get them from our API), it's only after interacting that all but the object that triggered the reorder get messed up.

  1. 如何停止/规避 item.order 从 INT 切换到 STRING 的行为?
  2. 如果这是不可能的,我怎么能强制我的 $index 是一个字符串,所以模型(字符串)匹配值(字符串)
  3. 如果这是不可能的,我如何编写我的 ng-options 以便获得我想要的行为?(我认真尝试了很多,从 track by 到不同的 as 和 for 语句,都导致了不同的错误)

    在初始加载时,所有选择都显示一个正确的选择值,所以所有 item.order 最初都是 INT(我从我们的 API 中获取它们),只有在交互之后,除了触发重新排序的对象之外的所有对象都被搞砸了。

采纳答案by thisisboris

Eventually I was able to solve this by doing:

最终,我能够通过执行以下操作来解决此问题:

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

This, and only this solution (so far) has what I want/need. I need the item.order model to keep track of the current position and to show the correct value on initial load. You can't set the model to questionIndex because that disturbs other HTML-elements, I can't set it to $index because that also did weird things.

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

While the other solutions suggested here 'work', they do not result in the spec that was given to me. So I guess this is kinda specific.

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

回答by ivarni

It gets changed to a string because HTML has no concept of what an integer is. Ultimately the selected variables is read from the DOM and handed to angular and so it changes its type.

它被更改为字符串,因为 HTML 没有整数是什么概念。最终选择的变量从 DOM 中读取并传递给 angular,因此它改变了它的类型。

You can force the model to always contain an integer with a directive

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

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)

噗嗤

But I see someone already pointed out that there might be better ways to keep track of the ordering. FWIW that directive will at least keep making sure the model is never a string.

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

回答by ThulasiramSoft

.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+'';
            });
        }
    }
});