使用angularjs保留光标位置

maa*_*nus 12 validation jquery angularjs

以下代码片段执行我想要的操作input,即删除所有非字母数字字符,转换为大写,并保留光标位置.

element = $(element);

element.keyup(function() {
    var x = element.val();
    var y = x && x.toUpperCase().replace(/[^A-Z\d]/g, '');
    if (x===y) return;
    var start = this.selectionStart;
    var end = this.selectionEnd + y.length - x.length;
    element.val(y);
    this.setSelectionRange(start, end);
});
Run Code Online (Sandbox Code Playgroud)

我把这个片段放在link一个指令中,它主要起作用.

问题是angular模型在应用更改之前看到了值.我曾试图谷歌如何使用$apply$digest在此处使用,但没有任何效果.

(实际上,我以某种方式管理它,但随后内容被重新渲染,我失去了位置.我无法重现它,但它还不够好,无论如何.)

Mic*_*mza 21

这样做的方法

  • 输入仅清理一次
  • ngChange 然后在输入上只触发一次

是使用ngModelController提供的$parsers数组.它被设计为影响模型值的位置(通过其返回值),但它也可以用作输入事件的监听器.

app.directive('cleanInput', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModelController) {
      var el = element[0];

      function clean(x) {
        return x && x.toUpperCase().replace(/[^A-Z\d]/g, '');
      }

      ngModelController.$parsers.push(function(val) {
        var cleaned = clean(val);

        // Avoid infinite loop of $setViewValue <-> $parsers
        if (cleaned === val) return val;

        var start = el.selectionStart;
        var end = el.selectionEnd + cleaned.length - val.length;

        // element.val(cleaned) does not behave with
        // repeated invalid elements
        ngModelController.$setViewValue(cleaned);
        ngModelController.$render();

        el.setSelectionRange(start, end);
        return cleaned;
      });
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

但是,我不确定这种用法$parsers是否有点像黑客.该指令可用作:

<input type="text" clean-input ng-model="name">
Run Code Online (Sandbox Code Playgroud)

或者如果你想要一个ngChange功能:

<input type="text" clean-input ng-model="name" ng-change="onChange()">
Run Code Online (Sandbox Code Playgroud)

这可以在http://plnkr.co/edit/dAJ46XmmC49wqTgdp2qz?p=preview上看到.