AngularJS 指令和表单验证中的动态必需属性
AngularJS dynamic required attribute in directive and form validation
我有一个指令,它从 REST api 接收元素是否应该 必需。现在,当属性设置为必需时,我似乎无法使表单无效。
所以,本质上我可以从下面的指令中动态添加 'required' 属性,但它不会使表单无效。查看 chrome 我发现,即使存在必需的属性,$error 数组中的必需条目也不存在。
app.directive('requireiftrue', function ($compile) {
return {
require: '?ngModel',
link: function (scope, el, attrs, ngModel) {
if (!ngModel) {
return;
}
if(attrs.requireiftrue==="true"){
console.log('should require');
el.attr('required', true);
$compile(el.contents())(scope);
}
else{
console.log('should not require');
}
}
};
});
这里有一个jsfiddle来说明问题。而且,这是从我休息 API
返回的示例 JSON
{
race: false,
martialStatus: true,
}
编辑: 虽然被接受的答案让我振作起来 运行,但我仍然有很多事情要做。
即:
1.解决延迟承诺以确保我的表单实际收到所需的字段以进行验证
2.观察我的'requireiftrue'属性
我的解决方案
模块配置:
function config($stateProvider) {
$stateProvider
.state('testState', {
url: '/test/form',
controller: 'TestCtrl',
templateUrl: 'test/form/testForm.tpl.html',
resolve: {
formDefaultService: function getFormDefaults($q, dataservice) {
// Set up a promise to return
var deferred = $q.defer();
var myData = dataservice.getFormDefaults();
deferred.resolve(myData);
return deferred.promise;
//return
}
},
data: {
pageTitle: 'Test Info'
}
});
}
最后,接收api数据的指令/HTML:
指令:
.directive('requireiftrue', function ($compile) {
return {
require: '?ngModel',
link: function (scope, el, attrs, ngModel) {
if (!ngModel) {
return;
}
attrs.$observe('requireiftrue', function(value){
if(value==="true"){
el.attr('required', true);
el.removeAttr('requireiftrue');
$compile(el[0])(scope);
}
});
}
};
});
HTML:
<input max="40"
requireiftrue={{defaults.validation.name}}
validNumber
id="name"
name="name"
type="text"
ng-model="test.name"
class="form-control">
尝试:
1. 将 required
指令添加到要对其应用验证的输入
<input id="inputEmail" class="requireiftrue" placeholder="Email"
ng-model="email" requireiftrue="true" required>
2 将指令定义为类型 class
并将指令 class 添加到 HTML 输入字段
JS
app.directive('requireiftrue', function ($compile) {
return {
restrict: 'C',
require: '?ngModel',
.....
HTML
<input id="inputEmail" class="requireiftrue" placeholder="Email" ng-model="email" requireiftrue="true" required>
这是您的更新 fiddle - http://jsfiddle.net/4fb6wg30/
您只需要将 "required" 属性添加到输入中。
<input max="40"
requireiftrue={{defaults.validation.name}}
validNumber
id="name"
name="name"
type="text"
ng-model="test.name"
class="form-control"
required="required">
不使用指令,而是使用 ng-init
来初始化 requireiftrue
。
并将此值分配给 ng-required
,如 ng-required="requireiftrue"
,如下所示。正如您所说,您正在从 rest api 获取数据,您可以使用从 api 获取的值初始化 requireiftrue
,而不是 true 或 false,如下例所示。
希望对您有所帮助。
已更新fiddle
http://jsfiddle.net/zsrfe513/3/
<form ng-app="form-example" name='fo' class="row form-horizontal" novalidate>
<div class="control-group" ng-form="testReq">
<h3>Form invalid: {{testReq.$invalid}}</h3>
<label class="control-label" for="inputEmail">Email</label>
<div class="controls" ng-init='requireiftrue = true'>
<input id="inputEmail" placeholder="Email" ng-model="email" name='ip' ng-required='requireiftrue'>
<span ng-show="testReq.ip.$dirty && testReq.ip.$error.required">
Required.
</span>
</div>
</div>
</form>
您有两个问题:
第一个是 el.contents() 返回一个空数组。所以你应该做的第一件事就是把它改成 el[0]。但是如果 el.contents() 起作用,你就会遇到更严重的问题。您可能一直在尝试编译一个指令,该指令本身就是一个会导致无限循环的指令(直到浏览器以任何方式崩溃)。
所以这是修改后的代码:
var app = angular.module('form-example', []);
app.directive('requireiftrue', function ($compile) {
return {
require: '?ngModel',
link: function (scope, el, attrs, ngModel) {
if (!ngModel) {
return;
}
if(attrs.requireiftrue==="true"){
console.log('should require');
el.attr('required', true);
el.removeAttr('requireiftrue');
$compile(el[0])(scope);
}
else{
console.log('should not require');
}
}
};
});
不过我要注意,现在这个指令是一次性的。如果模型会改变,指令将不再在元素上处理它。
我使用 <input ng-required="true">
对我的 angular 验证组件运行良好。
如果您使用新的 angular 组件,请确保传入 required: "@" 而不是 required: "="
scope: {
required: '@'
}
我也更进一步,并以同样的方式要求整数和 min/max 验证。
我有一个指令,它从 REST api 接收元素是否应该 必需。现在,当属性设置为必需时,我似乎无法使表单无效。
所以,本质上我可以从下面的指令中动态添加 'required' 属性,但它不会使表单无效。查看 chrome 我发现,即使存在必需的属性,$error 数组中的必需条目也不存在。
app.directive('requireiftrue', function ($compile) {
return {
require: '?ngModel',
link: function (scope, el, attrs, ngModel) {
if (!ngModel) {
return;
}
if(attrs.requireiftrue==="true"){
console.log('should require');
el.attr('required', true);
$compile(el.contents())(scope);
}
else{
console.log('should not require');
}
}
};
});
这里有一个jsfiddle来说明问题。而且,这是从我休息 API
返回的示例 JSON{
race: false,
martialStatus: true,
}
编辑: 虽然被接受的答案让我振作起来 运行,但我仍然有很多事情要做。
即: 1.解决延迟承诺以确保我的表单实际收到所需的字段以进行验证 2.观察我的'requireiftrue'属性
我的解决方案
模块配置:
function config($stateProvider) {
$stateProvider
.state('testState', {
url: '/test/form',
controller: 'TestCtrl',
templateUrl: 'test/form/testForm.tpl.html',
resolve: {
formDefaultService: function getFormDefaults($q, dataservice) {
// Set up a promise to return
var deferred = $q.defer();
var myData = dataservice.getFormDefaults();
deferred.resolve(myData);
return deferred.promise;
//return
}
},
data: {
pageTitle: 'Test Info'
}
});
}
最后,接收api数据的指令/HTML:
指令:
.directive('requireiftrue', function ($compile) {
return {
require: '?ngModel',
link: function (scope, el, attrs, ngModel) {
if (!ngModel) {
return;
}
attrs.$observe('requireiftrue', function(value){
if(value==="true"){
el.attr('required', true);
el.removeAttr('requireiftrue');
$compile(el[0])(scope);
}
});
}
};
});
HTML:
<input max="40"
requireiftrue={{defaults.validation.name}}
validNumber
id="name"
name="name"
type="text"
ng-model="test.name"
class="form-control">
尝试:
1. 将required
指令添加到要对其应用验证的输入 <input id="inputEmail" class="requireiftrue" placeholder="Email"
ng-model="email" requireiftrue="true" required>
2 将指令定义为类型 class
并将指令 class 添加到 HTML 输入字段
JS
app.directive('requireiftrue', function ($compile) {
return {
restrict: 'C',
require: '?ngModel',
.....
HTML
<input id="inputEmail" class="requireiftrue" placeholder="Email" ng-model="email" requireiftrue="true" required>
这是您的更新 fiddle - http://jsfiddle.net/4fb6wg30/
您只需要将 "required" 属性添加到输入中。
<input max="40"
requireiftrue={{defaults.validation.name}}
validNumber
id="name"
name="name"
type="text"
ng-model="test.name"
class="form-control"
required="required">
不使用指令,而是使用 ng-init
来初始化 requireiftrue
。
并将此值分配给 ng-required
,如 ng-required="requireiftrue"
,如下所示。正如您所说,您正在从 rest api 获取数据,您可以使用从 api 获取的值初始化 requireiftrue
,而不是 true 或 false,如下例所示。
希望对您有所帮助。
已更新fiddle http://jsfiddle.net/zsrfe513/3/
<form ng-app="form-example" name='fo' class="row form-horizontal" novalidate>
<div class="control-group" ng-form="testReq">
<h3>Form invalid: {{testReq.$invalid}}</h3>
<label class="control-label" for="inputEmail">Email</label>
<div class="controls" ng-init='requireiftrue = true'>
<input id="inputEmail" placeholder="Email" ng-model="email" name='ip' ng-required='requireiftrue'>
<span ng-show="testReq.ip.$dirty && testReq.ip.$error.required">
Required.
</span>
</div>
</div>
</form>
您有两个问题: 第一个是 el.contents() 返回一个空数组。所以你应该做的第一件事就是把它改成 el[0]。但是如果 el.contents() 起作用,你就会遇到更严重的问题。您可能一直在尝试编译一个指令,该指令本身就是一个会导致无限循环的指令(直到浏览器以任何方式崩溃)。 所以这是修改后的代码:
var app = angular.module('form-example', []);
app.directive('requireiftrue', function ($compile) {
return {
require: '?ngModel',
link: function (scope, el, attrs, ngModel) {
if (!ngModel) {
return;
}
if(attrs.requireiftrue==="true"){
console.log('should require');
el.attr('required', true);
el.removeAttr('requireiftrue');
$compile(el[0])(scope);
}
else{
console.log('should not require');
}
}
};
});
不过我要注意,现在这个指令是一次性的。如果模型会改变,指令将不再在元素上处理它。
我使用 <input ng-required="true">
对我的 angular 验证组件运行良好。
如果您使用新的 angular 组件,请确保传入 required: "@" 而不是 required: "="
scope: {
required: '@'
}
我也更进一步,并以同样的方式要求整数和 min/max 验证。