使用ngModel的自定义输入指令不会更新模型值

时间:2015-12-09 15:49:56

标签: javascript angularjs angularjs-directive

我想在自定义输入指令中使用ngPattern。为了解决这个问题,我首先创建了以下指令:

myApp.directive('myInput', [function() {
    return{
        restrict: 'A',
        replace: true,
        require: 'ngModel',
        scope: true,
        template:
            '<div>' +
            '  <input type="text" ng-model="val" ng-change="updateValue()" ng-pattern="/^-?(?:\d+|\d*\.(\d+)?)$/i">' +
            '</div>',
        link: function(scope, element, attrs, ngModelCtrl){     
            scope.updateValue = function(){
                ngModelCtrl.$setViewValue(scope.val);
            }

            ngModelCtrl.$render = function () {
                scope.val = ngModelCtrl.$viewValue;
            };
        }
    };
}]);

我在调试器中看到scope.val的值始终未定义,因此调用$setValue无效。我试图删除ng-pattern属性,但是更新也不起作用。

这里有什么问题?可以找到plunkr here,其中我绑定到模型而不是基元!

更新

似乎在ngModelCtrl.$setViewValue(scope.val)中调用scope.updateValue会产生奇怪的结果。如果有这样的模型:

scope.model = {
    'testValue' : 12
};

我绑定到"model.testValue"(如plunkr中所示),然后在执行{}后模型变为空对象ngModelCtrl.$setViewValue(scope.val)。在正常输入字段中再次设置该值会将scope.model变量重置为一个合理的对象。对我来说这毫无意义。知道为什么会这样吗?

2 个答案:

答案 0 :(得分:0)

我自己找到了解决方案。我不确定它是否是最佳方式,但它有效。我看到了类似于我的原始版本(在某种意义上说如何实现数据绑定)的类似指令,例如jkuri.touchSpin

重要的是要保留对ngModelController的原始$render函数的引用,并在使用$setViewValue后调用此函数。

但最终对我有用的是:

myApp.directive('myInput', ['$parse', function($parse) {
    return{
        restrict: 'A',
        replace: true,
        require: 'ngModel',
        scope: true,
        template:
            '<div>' +
            '  <input type="text" ng-model="val" ng-change="updateValue()"  ng-pattern="regex" >' +
            '</div>',
        link: function(scope, element, attrs, ngModelCtrl){
            var orignalRender = ngModelCtrl.$render;
            scope.regex = /^-?(?:\d+|\d*\.(\d+)?)$/i;
            ngModelCtrl.$render = function () {
                scope.val = ngModelCtrl.$viewValue;
            };              
            scope.updateValue = function(){
                ngModelCtrl.$setViewValue(scope.val);
                orignalRender();
            }
        }
    };
}]);

答案 1 :(得分:-1)