我希望创建一个自定义指令,该指令呈现为输入类型元素。该指令应该重用angularjs验证框架。以下是我创建的custom-input
指令:
<!doctype html>
<html ng-app="validationApp">
<body>
<div class="container" ng-controller="ValidationController as validationController">
<form name="myForm">
{{employee | json}}
<custom-input ng-required="true" ng-model="employee.name" name="employee.name" id="employeeName" ng-pattern="/^[0-9]{1,7}$/"/></custom-input>
<span ng-show="myForm['employee.name'].$error.required">This is a required field</span>
<span ng-show="myForm['employee.name'].$error.pattern">This is a invalid field</span>
</form>
</div>
<script type="text/ng-template" id="/templates/customInput.html">
<div>
<input type="text" name="{{name}}" ng-model="newInput" id="{{id}}">
</div>
</script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js"></script>
</body>
</html>
与此对应的javascript是:
angular.module('validationApp', [])
.controller("ValidationController", function(){
})
.directive("customInput", function(){
return {
restrict: "E",
require : "ngModel",
replace: "true",
templateUrl : "/templates/customInput.html",
scope : {
id : "@", //bind id to scope
name : "@" //bind name to scope
},
link: function(scope, element, attrs, ngModelCtrl){
//When newInput is updated, update the model of original input
scope.$watch('newInput', function(newValue){
ngModelCtrl.$setViewValue(newValue);
});
//On first load, get the initial value of original input's model and assign it to new input's model
ngModelCtrl.$render = function(){
var viewValue = ngModelCtrl.$viewValue;
if(viewValue){
scope.newInput = viewValue;
}
}
}
}
});
我正在尝试对此自定义输入应用ng-required
和ng-pattern
验证。我遇到了两个问题:
ng-required
中激活custom-input
验证,但在1.3.0中,验证不会被解雇。ng-pattern
验证。 我的理解是$setViewValue
ngModelController
将触发所有验证。以上是一个人为的例子,我的实际用例是创建一个自定义指令,它为SSN呈现三个输入框。
以下是1.2.6和1.3.0的plunker链接:
答案 0 :(得分:4)
要让ng-required
生效,不要在内部输入表单的输入上具有相同的名称。我看来,在Angular 1.3中,这会覆盖附加到ngModelController
的已注册custom-input
。
因此指令的模板可以是
<div>
<input type="text" ng-model="newInput" id="{{id}}">
</div>
这可以在http://plnkr.co/edit/TqMkxV?p=preview工作。
(另外,不知道为什么你需要id ...)
我认为(但我不确定)在1.2.6 ngPattern
中仅适用于input
元素,而在1.3中它是一个与之集成的独立指令ngModel。另外,要使它在1.3
pattern
代替ng-pattern
,即使文档建议ng-pattern
应该有效。如果您直接在模板中编写模式,请不要将其包装在/
... /
中。因此正确使用它寻找正好5位数将是pattern="^\d{5}$"
。这些文档在这方面具有误导性。
pattern
的工作示例
评论后编辑:
如果您确实希望该名称出现在内部指令上,并且与父元素名称相同(例如,使用标准整页POST提交到服务器),您可以将其包装在一个名为{{ 1}}。这将确保其控制器不会覆盖范围中的父控制器。
ngForm
答案 1 :(得分:0)
在指令内的隔离范围内,尝试使用'='而不是'@'
绑定它对于@,如果需要使用link(ing)函数中的值,则需要使用attr。$ observe('title',function(value){...})。例如,if(scope.title ==“...”)将不会像您期望的那样工作。请注意,这意味着您只能异步访问此属性。如果仅使用模板中的值,则不需要使用$ observe()。例如,模板:'{{title}}'。
使用=,您不需要使用$ observe。
(FROM What is the difference between '@' and '=' in directive scope in AngularJS?)
angular.module('validationApp', [])
.controller("ValidationController", function(){
})
.directive("customInput", function(){
return {
restrict: "E",
require : "ngModel",
replace: "true",
templateUrl : "/templates/customInput.html",
scope : {
id : "=", //bind id to scope
name : "=" //bind name to scope
},
link: function(scope, element, attrs, ngModelCtrl){
//When newInput is updated, update the model of original input
scope.$watch('newInput', function(newValue){
ngModelCtrl.$setViewValue(newValue);
});
//On first load, get the initial value of original input's model and assign it to new input's model
ngModelCtrl.$render = function(){
var viewValue = ngModelCtrl.$viewValue;
if(viewValue){
scope.newInput = viewValue;
}
}
}
}
});
答案 2 :(得分:0)
根据文件(https://docs.angularjs.org/guide/migration), 正则表达式字符串用作角度1.2中ng-pattern的值。相反,在1.3中使用正则表达式对象。
// 1.2
$scope.exp = '/abc/i'; //string
<input ng-pattern="{{exp}}" ...
// 1.3
$scope.exp = /abc/i; //regexp object
<input ng-pattern="exp" ...
这是我的自定义输入指令示例
角度1.2.16:http://jsfiddle.net/miyukiw/m03f2ymt/4/
角度1.3.5:http://jsfiddle.net/miyukiw/9d64oa1m/4/
我希望这会有所帮助。