Input cursor position jumps to end with ng-change()

北城以北 提交于 2019-12-01 23:41:22
Maxim Shoustin

The cursor goes to the end because we modify data by using parseInt.

I suggest you to store the caret position before and then when you're done doing things, set it back.

This example might help you: Link

Two suggestions:

1 Why not just use number input.

<div ng-app='myApp'>
    <div ng-controller="myCtrl">
    <input id="compute1" ng-model="compute.c1" ng-change="math()" type="number"/>
    <input id="compute2" ng-model="compute.c2" ng-change="math()" type="number"/>
  </div>
</div>

2 Two-Way databinding should always be used with the "dot" notation:

$scope.compute = {c1: 0, c2: 10};

$scope.math = function() {
  $scope.compute.c1 = parseInt($scope.compute.c1);
  $scope.compute.c2 = parseInt($scope.compute.c2);
};

and update your html accordingly to have ng-model="compute.c1" etc.

codebreach

Depending on what math() does, you could make the computation happen on blur instead of change. This way the conversion will only happen when the user tabs (or clicks) out of the input.

See Angularjs: input[text] ngChange fires while the value is changing for an example of this.

I just wrote this directive which basically allows you to format the text and keep cursor position it's not flawless but works pretty well. Just make sure to return the value in the format function instead of actually changing the value and use it the same as you would the regular ng-change:

.directive('ngChangeFormat', function() {
        return {
            restrict: 'A',
            require: '?ngModel',
            link: function(scope, element, attr, controller) {
                controller.$viewChangeListeners.push(function() {
                    var el = element[0];
                    var start = el.selectionStart;
                    var end = el.selectionEnd;
                    var originalValue = controller.$viewValue;
                    var formattedValue = scope.$eval(attr.ngChangeFormat);
                    controller.$setViewValue(formattedValue);
                    controller.$render();
                    if(start === originalValue.length)
                        el.setSelectionRange(formattedValue.length, formattedValue.length);
                    else
                        el.setSelectionRange(start, end);
                });
            }
        };
    })

Very quick and simple fix to delay the ng-model-options. I had the same issue this worked for me: on your input ->

ng-model-options="{debounce: 750}"
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!