AngularJS:模型转换后,游标移至最后一个位置

时间:2018-09-26 20:14:11

标签: angularjs angularjs-directive angularjs-scope

我正在使用zipcode指令,该指令接受9位美国邮政编码并对其进行格式化。

app.directive('formatZipCode', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attr, ngModelCtrl) {
            function fromUser(text) {
                if (text) {
                    var transformedInput = text.replace(/[^0-9]/g, '');
                    if (transformedInput.length > 9) {
                        transformedInput = transformedInput.slice(0, 9);
                    }
                    if (transformedInput.length > 5) {
                        transformedInput = transformedInput.slice(0, 5) + "-" + transformedInput.slice(5);
                    }

                    if (transformedInput !== text) {
                        ngModelCtrl.$setViewValue(transformedInput);
                        ngModelCtrl.$render();
                    }
                    return transformedInput;
                }
                return undefined;
            }


            ngModelCtrl.$parsers.push(fromUser);
        }
    };
});

当我从邮政编码中删除任何数字时,光标位置移回到最后一个位置。 When I delete third number cursor moves to last number

如何保留光标位置?

2 个答案:

答案 0 :(得分:0)

您最好的选择是使用ng-model-options来更改输入的更新时间(从而运行格式化程序)。

在这种情况下,您将牺牲实时重新格式化以支持表单可用性。

可以使用

<input type="text" ng-model="zipcode" ng-model-options="{ updateOn: 'blur' }" format-zip-code /> 

在用户离开字段时进行更新,或者

<input type="text" ng-model="zipcode" ng-model-options="{ debounce: 1000 }" format-zip-code />

1s之后更新。此选项仍将显示更新后光标移动到输入的末尾,但不是立即移动。

答案 1 :(得分:0)

我已经通过插入符号的位置解决了这个问题。记住插入标记的位置,并在格式化输入后再次分配插入标记的位置。

app.directive('formatZipCode', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attr, ngModelCtrl) {
            function fromUser(text) {
                if (text) {
                    var transformedInput = text.replace(/[^0-9]/g, '');
                    if (transformedInput.length > 9) {
                        transformedInput = transformedInput.slice(0, 9);
                    }
                    var caretPosition = element[0].selectionStart || undefined;
                    if (transformedInput.length > 5) {                     
                        var realposition = caretPosition == 6 ? caretPosition + 1 : caretPosition;
                        transformedInput = transformedInput.slice(0, 5) + "-" + transformedInput.slice(5);
                    }

                    if (transformedInput !== text) {                      
                        ngModelCtrl.$setViewValue(transformedInput);
                        ngModelCtrl.$render();
                        if (typeof caretPosition === 'number') {
                            element[0].selectionStart = element[0].selectionEnd = realposition || caretPosition;
                        }
                        else {
                            element[0].selectionStart = element[0].selectionEnd = 0;
                        }
                    }
                    return transformedInput;
                }
                return undefined;
            }

            ngModelCtrl.$parsers.push(fromUser);
        }
    };
});