简体   繁体   English

AngularJS动态需要在指令和表单验证中的属性

[英]AngularJS dynamic required attribute in directive and form validation

I have a directive that receives whether an element should be required or not from a REST api . 我有一个指令,用于接收REST API中是否需要元素。 Right now, I can't seem to get the form to invalidate when an attribute is set to required. 现在,当属性设置为required时,我似乎无法使表单无效。

So, in essence I'm able to dynamically add the 'required' attribute from the directive below, but it doesn't invalidate the form. 因此,本质上我能够从下面的指令动态添加'required'属性,但它不会使表单无效。 Looking through chrome I see that, even though the required attribute exists, a required entry in the $error array doesn't exist. 通过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');   
            }
        }
    };
});

Here's a jsfiddle to illustrate the problem. 这是一个解释问题的方法。 And, here's sample JSON returned from my rest API 而且,这是从我的rest API返回的示例JSON

{
    race: false,
    martialStatus: true,
}

EDIT: While the accepted answer got me up and running, I still had a good bit of finagling to do. 编辑:虽然接受的答案让我开始运行,但我仍然有很多需要做的事情。

Namely: 1. Resolving a deferred promise to ensure that my form actually receives the required fields to validate 2. observing my 'requireiftrue' attribute 即:1。解决延期承诺,以确保我的表单实际上收到必要的字段以进行验证2.观察我的'requireiftrue'属性

My solution 我的解决方案

module config: 模块配置:

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'
        }
    });
}

And, finally the directive / HTML that receives api data: 最后,接收api数据的指令/ HTML:

Directive: 指示:

.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: HTML:

<input max="40"
requireiftrue={{defaults.validation.name}}
validNumber
id="name"
name="name"
type="text"
ng-model="test.name"
class="form-control">

You had two issues: The first is el.contents() returned an empty array. 你有两个问题:第一个是el.contents()返回一个空数组。 so The first thing you should do is change it to el[0]. 所以你应该做的第一件事就是把它改成el [0]。 But had el.contents() worked you would hav had a much more serious problem. 但如果el.contents()工作,你会遇到更严重的问题。 You would have been trying to compile a directive that has itself as a directive which would lead to an infinite loop (well until the browser crashed any way). 您本来一直在尝试编译一个指令,该指令将自身作为指令导致无限循环(直到浏览器以任何方式崩溃)。 So here is the revised code: 所以这是修改后的代码:

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');   
            }
        }
    };
});

I should note however that now this directive is a one-off. 但我应该注意到,现在这个指令是一次性的。 If the model will change, the directive will not be on the element any longer to deal with it. 如果模型将发生变化,则该指令将不再在该元素上处理它。

Instead of using a directive, use ng-init to initialize requireiftrue . 而不是使用指令,使用ng-init来初始化requireiftrue and assign this value to ng-required like ng-required="requireiftrue" as shown below. 并将此值分配给ng-requiredng-required="requireiftrue" ,如下所示。 As you said you are getting the data from rest api, you can initialize requireiftrue with the value you are getting from api, instead of true or false as shown in example below. 如您所说,您从rest api获取数据,您可以使用从api获得的值初始化requireiftrue ,而不是true或false,如下面的示例所示。

Hope this helps you. 希望这对你有所帮助。

Updated fiddle http://jsfiddle.net/zsrfe513/3/ 更新小提琴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>

Try: 尝试:

1. adding the required directive to the input you want to apply validation to 1.将required指令添加到要应用验证的输入

 <input id="inputEmail" class="requireiftrue" placeholder="Email" ng-model="email" requireiftrue="true" required> 
2 Defining the directive as type class and adding the directive class to the HTML input field 2将指令定义为类型class ,并将指令类添加到HTML输入字段

JS JS

<input id="inputEmail" class="requireiftrue" placeholder="Email" ng-model="email" requireiftrue="true" required>

HTML HTML

 <input id="inputEmail" class="requireiftrue" placeholder="Email" ng-model="email" requireiftrue="true" required> 

here is a update of your fiddle - http://jsfiddle.net/4fb6wg30/ 这是你的小提琴的更新 - http://jsfiddle.net/4fb6wg30/

You just need to add the "required" attribute to the input. 您只需要在输入中添加“required”属性。

<input max="40"
requireiftrue={{defaults.validation.name}}
validNumber
id="name"
name="name"
type="text"
ng-model="test.name"
class="form-control"
required="required">

I used <input ng-required="true"> worked fine for my angular validation component. 我使用<input ng-required="true">为我的角度验证组件工作正常。

If your using the new angular component make sure to pass in required: "@" instead of required: "=" 如果您使用新的角度组件,请务必传入所需的内容:“@”而不是必需的:“=”

scope: {
      required: '@'
    }

I also took this further and required integer and min/max validation the same way. 我也进一步采用了这种方法,并以相同的方式进行了整数和最小/最大验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM