在指令中使用ng-repeat导致表单验证无法正常工作

时间:2015-05-14 03:59:04

标签: angularjs validation angularjs-directive angularjs-ng-repeat

在html中,

<form name="textform" novalidate>
    <cms-radio name="color" require="true" option="[{title:'Red', value:'red'},{title:'Orange', value:'orange'},{title:'Green', value:'green'}]" ng-model="color"></cms-radio>
</form>

在JS中,

angular.module('cmsRadio',[]).directive('cmsRadio', function(){
'use strict';

    return {
        restrict: 'E',
        scope: {
            name:'@',
            require:'=',
            option:"=",
            bindedModel: "=ngModel"
        },
        replace:true,    
        templateUrl: 'radio.html'
    };
});

在radio.html中

<div class="form-group" ng-form="{{name}}" ng-class="{'has-error':{{name}}.$invalid && {{name}}.$dirty}" >
    <div class="radio" ng-repeat='item in option'>
           <label><input type="radio" name="{{name}}" ng-model="bindedModel" value="{{item.value}}" ng-required="require">{{item.title}}</label>
    </div>
    <span class="has-error" ng-show='{{name}}.$dirty && {{name}}.$invalid' ng-message='{{name}}.$error'>
            <p class="control-label" ng-messsage='require'>{{name}} is required.</p>
    </span>
</div>

当我点击第一个单选按钮时,它会显示如下错误。

enter image description here

只有点击了三个单选按钮,错误才会消失。如果只点击其中一个单选按钮而不是三个,如何防止出现错误?有人可以帮忙吗?

编辑:我的解决方案

在html中,

<cms-radio label="Color" name="color" require="true" option="[{'answers':[{'title':'Red', 'value':'red'},{'title':'Orange', 'value':'orange'},{'title':'Green', 'value':'green'}],'selectedAnswer':null}]" id="color" class=""></cms-radio>

在JS中,

 angular.module('cmsRadio',[]).directive('cmsRadio', function(){
    'use strict';

        return {
            restrict: 'E',
            scope: {
                name:'@',
                require:'=',
                option:"="
            },
            replace:true,    
            templateUrl: 'radio.html'
        };
    });

在radio.html中

<div class="form-group" ng-form="{{name}}" ng-class="{'has-error':{{name}}.$invalid && {{name}}.$dirty}" >
        <div ng-repeat="item in option">
            <div class="radio" ng-repeat="answer in item.answers">
                  <label><input type="radio" name="{{name}}" ng-model="item.selectedAnswer" value="{{answer.value}}" ng-required="require">{{answer.title}}</label>
            </div>
        </div>
        <span class="has-error" ng-show='{{name}}.$dirty && {{name}}.$invalid' ng-message='{{name}}.$error'>
                <p class="control-label" ng-messsage='require'>{{name}} is required.</p>
        </span>
</div>

1 个答案:

答案 0 :(得分:1)

我不会在ng-show和ng-class指令中插入字段名称。

不要为表单和输入名称复制scope.name,而是尝试给表单一个固定名称(例如'radioList'),例如:

<div class="form-group" ng-form="radioList" ng-class="{'has-error':radioList[name].$invalid && radioList[name].$dirty}" >
    <div class="radio" ng-repeat='item in option'>
           <label><input type="radio" name="{{name}}" ng-model="bindedModel" value="{{item.value}}" ng-required="require">{{item.title}}</label>
    </div>
    <span class="has-error" ng-show='radioList[name].$dirty && radioList[name].$invalid' ng-message='radioList[name].$error'>
            <p class="control-label" ng-messsage='require'>{{name}} is required.</p>
    </span>
</div>

<强>更新

上面的答案是错误的。这个问题与名称的插值无关。简单地说,ng-repeat正在创建一个子范围,而ng-model没有'。'。在其中,因此每个子范围都有自己的bindedmodel

副本

如果指令使用controllerAs选项,这不会有问题。但是,我们直接使用范围的最简单的解决方案是使用$parent补偿子范围,如下所示:

<div class="form-group" ng-class="{'has-error':{{name}}.$invalid && {{name}}.$dirty}" >
    <div class="radio" ng-repeat='item in option'>
           <label><input type="radio" name="{{name}}" ng-model="$parent.bindedModel" value="{{item.value}}" ng-required="require && !bindedModel">{{item.title}}</label>
    </div>
    <span class="has-error" ng-show="{{name}}.$invalid  && {{name}}.$dirty" ng-messages='{{name}}.$error'>
      <p class="control-label" ng-messsage='require'>{{name}} is required.</p>
    </span>
</div>

更新了plunkr