尽管设置了去抖动,如何立即设置输入的ngModel的$ viewValue

时间:2015-03-02 04:38:47

标签: angularjs angularjs-ng-model

假设我想对文本输入应用屏蔽功能。可以对电话号码输入进行适当的样式化(例如,输入5553334444,输出(555) 333-4444),或者只是将输入控件中的值设为大写。

我知道的方法使用ngModel控制器(通过require: "ngModel")并在$viewValue函数中设置新的大写$parser

ngModel.$parsers.unshift(function(val){
  var uppercase = val && val.toUpperCase();
  if (uppercase !== val){
    ngModel.$setViewValue(uppercase);
    ngModel.$render();
  }
  return uppercase;
});

但现在,假设我想使用ng-model-options="{debounce: 400}",因为我不想过快地触发模型中的更改:

<input ng-model="foo" ng-model-options="{debounce: 400}"
       ng-change="doBackendQuery(foo)"
       uppercase>

在上面的示例中,我不想过快地触发doBackendQuery,因为它会进行HTTP调用。 debounce会阻止这种情况发生,但它也会阻止uppercase指令立即执行,导致用户看到小写文本。

:如何立即编写uppercase指令来更改$viewValue,而无需等待debounce

(注意:我不想对底层DOM元素做出假设 - 这会违背DOM不可知的概念ng-model

plunker

3 个答案:

答案 0 :(得分:2)

一个hacky解决方案(未经测试):

<input ng-model="foo" ng-model-options="{debounce: 400}"
   ng-change="doBackendQuery(foo)"
   uppercase style="text-transform: uppercase;">

您还可以更改uppercase指令以自动设置该样式,或使用css:

input[uppercase] {
    text-transform: uppercase;
}

答案 1 :(得分:1)

这对我有用:

app.directive('capitalize', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, modelCtrl) {
            element.on('input', function() {
                var capitalized = element.val().toUpperCase();
                element.val(capitalized);
                modelCtrl.$setViewValue(capitalized);
            });

            modelCtrl.$parsers.push(function(value) {
                return value.toUpperCase();
            });
        }
    };
});

答案 2 :(得分:0)

(function(){

    angular
        .module('example', [])
        .directive('uppercase', [function(){
            return {
                restrict: 'A',
                require: 'ngModel',
                link: function(scope, iElem, iAttrs, ngModel){

                    iElem.on('input', function(){
                        var elem = angular.element(this),
                            valOrigin = elem.val();
                        
                        val = toUpperCase(valOrigin);

                        elem.val( val );

                        ngModel.$viewValue = toLowerCase(valOrigin);
                    });

                    ngModel.$parsers.push(function(value){
                        value = toLowerCase(value);

                        return value;
                    });

                    ngModel.$formatters.push(function(value){
                        value = toUpperCase(value);

                        return value;
                    });

                    function toLowerCase(value){
                        return (value + '').toLowerCase();
                    }

                    function toUpperCase(value){
                        return (value + '').toUpperCase();
                    }

                }
            }
        }])
        .controller('ExampleController', [function() {
            
            var vc = this;

            vc.user = {
                name: 'let\' start!'
            };

        }]);

    angular
        .bootstrap(document, ['example']);

})();
<script src="https://code.angularjs.org/1.4.7/angular.min.js"></script>

<div ng-controller="ExampleController as example">
  <form name="userForm">

    <label>Name:
      <input type="text" name="userName" uppercase ng-model="example.user.name" ng-model-options="{debounce: 500}" />
    </label>

    <p>Name: <span>{{ example.user.name }}</span></p>

  </form>
</div>