Angularjs在同一元素的指令中修改ng-model,并进行验证
Angularjs change ng-model within a directive on the same element with validations
在最原始的angular应用中,我试图为一个输入字段创建一个指令,它可以改变父节点的ng-model值。
HTML:<form novalidate>
<input ng-model="ctrl.myvalue" mydirective minlength="19" />
{{ ctrl.myvalue }}
</form>
JS:
var app = angular.module('app', []);
app.directive('mydirective', function(){
return {
scope: { ngModel: '=' },
link: function(scope, el) {
el.on('input', function(e) {
this.value = this.value.replace(/ /g,'');
scope.ngModel = this.value;
})
}
}
})
app.controller('MyController', function(){
this.myvalue = '';
})
砰砰作响
问题是,如果我使用这个指令与minlength
或pattern
一起输入验证,它会得到一个特定的行为:每第二个字母你输入消失;ng-model
也得到undefined
值。没有验证,代码可以完美地工作。
我也试图创建一个自定义验证作为一个解决方案,但它有相同的效果。
你能解释一下或建议怎么走吗?
您可以在第一次迭代中使用unsift,以及render。通常你可以使用ctrl.$setViewValue
,但你可以确保当值不改变时不重新启动…
var testModule = angular.module('myModule', []);
testModule.controller('testCntrl', ['$scope', function ($scope) {
$scope.test = 'sdfsd fsdf sdfsd sdf';
}]);
testModule.directive('cleanSpaces', [function () {
return {
require: '?ngModel',
link: function (scope, $elem, attrs, ctrl) {
if (!ctrl) return;
var filterSpaces = function (str) {
return str.replace(/ /g, '');
}
ctrl.$parsers.unshift(function (viewValue) {
var elem = $elem[0],
pos = elem.selectionStart,
value = '';
if (pos !== viewValue.length) {
var valueInit = filterSpaces(
viewValue.substring(0, elem.selectionStart));
pos = valueInit.length;
}
//I launch the regular expression,
// maybe you prefer parse the rest
// of the substring and concat.
value = filterSpaces(viewValue);
$elem.val(value);
elem.setSelectionRange(pos, pos);
ctrl.$setViewValue(value);
return value;
});
ctrl.$render = function () {
if (ctrl.$viewValue) {
ctrl.$setViewValue(filterSpaces(ctrl.$viewValue));
}
};
}
};
}]);
http://jsfiddle.net/luarmr/m4dmz0tn/UPDATE我用最后的代码和angular中的验证示例更新了fiddle,并用ng-trim (ngModel)更新了html。
使用Angular的NgModelController。我只是添加到$解析器(在视图更新时执行的函数,但在值被持久化到模型之前)。这里,我将函数推入$parsers管道。请记住,在最小长度验证得到满足之前,不会填充模型。代码片段显示了$viewValue和modelValue
var app = angular.module('app', []);
app.directive('mydirective', function() {
return {
require: 'ngModel',
priority: 100,
link: function(scope, el, attrs, ngModelCtrl) {
// $parsers from view/DOM to model
ngModelCtrl.$parsers.push(function(value) {
console.log(value);
return value && value.replace(/ /g, '');
});
}
}
})
app.controller('MyController', function() {
this.myvalue = '';
})
<script src="https://code.angularjs.org/1.4.0/angular.min.js"></script>
<div ng-app="app" ng-controller="MyController as ctrl">
<form name="myForm" novalidate>
<input ng-model="ctrl.myvalue" name="myValue" mydirective minlength="19" /><br /><br />Model Value: {{ ctrl.myvalue }}<br /><br />
View Value: {{ myForm.myValue.$viewValue }}
</form>
</div>
Update:如果您正在尝试执行自定义验证,请忘记最小长度/必需的东西,只需编写自己的内容。在用户键入时更改文本可能不是最好的行为。这个例子将在模糊事件的viewValue中添加空格。我仍然认为ngModelController是要走的路,但我不知道你想要完成什么,给你更接近你正在寻找的东西。
var app = angular.module('app', []);
app.directive('creditCardValidator', function() {
return {
require: 'ngModel',
priority: 100,
link: function(scope, el, attrs, ngModelCtrl) {
// 16 characters
attrs.$set('maxlength', 16);
var noSpaces = function noSpaces(value) {
return value.replace(/ /g, '');
}
var withSpaces = function withSpaces(value) {
if (ngModelCtrl.$isEmpty(value)) {
return;
}
var spacedValue = value.replace(/('d{4})('d{4})('d{4})('d{4})/, '$1 $2 $3 $4');
return spacedValue || undefined;
}
ngModelCtrl.$parsers.push(noSpaces);
ngModelCtrl.$formatters.push(withSpaces);
ngModelCtrl.$validators.validCreditCard = function(modelValue, viewValue) {
var value = noSpaces(modelValue || viewValue);
var valid = /^'d{16}$/.test(value);
return valid;
};
el.on('blur', function() {
if (ngModelCtrl.$valid) {
ngModelCtrl.$setViewValue(withSpaces(ngModelCtrl.$modelValue));
ngModelCtrl.$render();
}
});
}
}
})
app.controller('MyController', function() {
this.myvalue = '';
})
<script src="https://code.angularjs.org/1.4.0/angular.min.js"></script>
<div ng-app="app" ng-controller="MyController as ctrl">
<form name="myForm" novalidate>
<input ng-model="ctrl.myvalue" name="myValue" ng-model-options="{allowInvalid: true}" credit-card-validator />
<br />
<br />Model Value: {{ ctrl.myvalue }}
<br />
<br />View Value: {{ myForm.myValue.$viewValue }}
<br />
<br />Error: {{ myForm.myValue.$error }}
</form>
</div>
相关文章:
- 从 Javascript 中设置 ng-model name
- Toggle Switch在包含ng model和ng repeat之后不进行切换
- 在Angularjs中,我如何使用ng repeat、ng model和ng click来动态更改内容
- 当与之关联的 ng-model 为 false 时,Angularjs 复选框值不会取消选中
- ng-model 绑定到选择标签生成的空默认值
- 对象不能在angularjs ng-model中访问
- 为什么 HTML 中的 Value 属性在与 AngularJS 中的 ng-model 一起使用时不起作用
- ng-repeat不绑定ng-model对象数组
- AngularJS:ng-model 绑定在使用 jQuery 更改时不会更新
- 选择/选项 ng-model 未绑定 ng-selected
- Angular ng-model 将数据作为数组发送到 rails-api
- 正在使用ng消息验证动态表单
- ng模式验证在safari中不起作用
- 为什么 AngularJS 在使用 ng-model 时不会在文本框上设置长度属性
- AngularJS:Ng:init-如何分配Ng:model
- 在指令中使用 ng-model 和 ng-repeat
- 使用 angularjs 访问控制器中的 ng-model 数据
- 如何在 Angularjs 中为 ng-model 增加价值
- 在Angularjs中,“ng-model”属性在验证中的意义是什么?
- Angularjs在同一元素的指令中修改ng-model,并进行验证