[html] 如何验证使用ng-repeat动态创建的输入,ng-show(angular)


Answers

由于问题被问及,Angular团队通过动态创建输入名称来解决此问题。

使用Angular版本1.3和更高版本,您现在可以执行此操作:

<form name="vm.myForm" novalidate>
  <div ng-repeat="p in vm.persons">
    <input type="text" name="person_{{$index}}" ng-model="p" required>
    <span ng-show="vm.myForm['person_' + $index].$invalid">Enter a name</span>
  </div>
</form>

Demo

Angular 1.3还引入了ngMessages,这是一种更强大的表单验证工具。 你可以对ngMessages使用相同的技术:

<form name="vm.myFormNgMsg" novalidate>
    <div ng-repeat="p in vm.persons">
      <input type="text" name="person_{{$index}}" ng-model="p" required>
      <span ng-messages="vm.myFormNgMsg['person_' + $index].$error">
        <span ng-message="required">Enter a name</span>
      </span>
    </div>
  </form>
Question

我有一个使用ng-repeat创建的表格。 我想为表格中的每个元素添加验证。 问题是每个输入单元格的名称都与它上面和下面的单元格的名称相同。 我试图使用{{$index}}值来命名输入,但尽管HTML中的字符串文字显示正确,但它现在正在工作。

这是我现在的代码:

<tr ng-repeat="r in model.BSM ">
   <td>
      <input ng-model="r.QTY" class="span1" name="QTY{{$index}}" ng-pattern="/^[\d]*\.?[\d]*$/" required/>
      <span class="alert-error" ng-show="form.QTY{{$index}}.$error.pattern"><strong>Requires a number.</strong></span>
      <span class="alert-error" ng-show="form.QTY{{$index}}.$error.required"><strong>*Required</strong></span>
   </td>
</tr>

我尝试从索引中删除{{}} ,但这也不起作用。 截至目前,输入的验证属性正常工作,但不显示错误消息。

任何人有任何建议?

编辑:除了下面的杰出答案之外,这里还有一篇博客文章更详细地介绍了这个问题: http://www.thebhwgroup.com/blog/2014/08/angularjs-html-form-design-part-2/ : http://www.thebhwgroup.com/blog/2014/08/angularjs-html-form-design-part-2/




这是可能的,这里是我如何用输入表做同样的事情。

用这样的形式包装表格

那就用这个吧

我有一个带有多重嵌套指令的表单,它们都包含输入,选择等等......这些元素都包含在ng-repeats和动态字符串值中。

这是如何使用指令:

<form name="myFormName">
  <nested directives of many levels>
    <your table here>
    <perhaps a td here>
    ex: <input ng-repeat=(index, variable) in variables" type="text"
               my-name="{{ variable.name + '/' + 'myFormName' }}"
               ng-model="variable.name" required />
    ex: <select ng-model="variable.name" ng-options="label in label in {{ variable.options }}"
                my-name="{{ variable.name + index + '/' + 'myFormName' }}"
        </select>
</form>

注意:如果你需要序列化一个输入表,你可以添加和索引字符串连接; 这就是我所做的。

app.directive('myName', function(){

  var myNameError = "myName directive error: "

  return {
    restrict:'A', // Declares an Attributes Directive.
    require: 'ngModel', // ngModelController.

    link: function( scope, elem, attrs, ngModel ){
      if( !ngModel ){ return } // no ngModel exists for this element

      // check myName input for proper formatting ex. something/something
      checkInputFormat(attrs);

      var inputName = attrs.myName.match('^\\w+').pop(); // match upto '/'
      assignInputNameToInputModel(inputName, ngModel);

      var formName = attrs.myName.match('\\w+$').pop(); // match after '/'
      findForm(formName, ngModel, scope);
    } // end link
  } // end return

  function checkInputFormat(attrs){
    if( !/\w\/\w/.test(attrs.rsName )){
      throw myNameError + "Formatting should be \"inputName/formName\" but is " + attrs.rsName
    }
  }

  function assignInputNameToInputModel(inputName, ngModel){
    ngModel.$name = inputName
  }

  function addInputNameToForm(formName, ngModel, scope){
    scope[formName][ngModel.$name] = ngModel; return
  }

  function findForm(formName, ngModel, scope){
    if( !scope ){ // ran out of scope before finding scope[formName]
      throw myNameError + "<Form> element named " + formName + " could not be found."
    }

    if( formName in scope){ // found scope[formName]
      addInputNameToForm(formName, ngModel, scope)
      return
    }
    findForm(formName, ngModel, scope.$parent) // recursively search through $parent scopes
  }
});

这应该处理很多情况,你只是不知道表单的位置。 或者您可能嵌套了表单,但出于某种原因,您希望将此输入名称附加到两个表单中? 那么,只需传入您想要附加输入名称的表单名称即可。

我想要的是一种将动态值分配给我永远不会知道的输入的方法,然后调用$ scope.myFormName。$ valid。

你可以添加任何你想要的东西:更多的表格更多的表单输入,嵌套表单,无论你想要什么。 只需传递您想要验证输入的表单名称即可。 然后在表单提交中询问$ scope.yourFormName。$ valid




这里有一个我如何做的例子,我不知道它是否是最好的解决方案,但完美的作品。

首先,用HTML代码。 看看ng类,它调用hasError函数。 还请看输入的名称声明。 我使用$索引来创建不同的输入名称。

<div data-ng-repeat="tipo in currentObject.Tipo"
    ng-class="{'has-error': hasError(planForm, 'TipoM', 'required', $index) || hasError(planForm, 'TipoM', 'maxlength', $index)}">
    <input ng-model="tipo.Nombre" maxlength="100" required
        name="{{'TipoM' + $index}}"/>

现在,这里是hasError函数:

$scope.hasError = function (form, elementName, errorType, index) {
           if (form == undefined
               || elementName == undefined
               || errorType == undefined
               || index == undefined)
               return false;

           var element = form[elementName + index];
           return (element != null && element.$error[errorType] && element.$touched);
       };



纵观这些解决方案,Al Johri提供的解决方案与我的需求最为接近,但他的指令稍微不能编程,而我想要。 这是我的解决方案版本:

angular.module("app", [])
    .directive("dynamicFormName", function() {
        return {
            restrict: "A",
            priority: 0,
            require: ["form"],
            compile: function() {
                return {
                    pre: function preLink(scope, iElement, iAttrs, ctrls) {
                        var name = "field" + scope.$index;

                        if (iAttrs.dnfnNameExpression) {
                            name = scope.$eval(iAttrs.dnfnNameExpression);
                        }

                        var parentForm = iElement.parent().controller("form");
                        if (parentForm) {
                            var formCtrl = ctrls[0];
                            delete parentForm[formCtrl.$name];
                            formCtrl.$name = name;
                            parentForm[formCtrl.$name] = formCtrl;
                        }
                    }
                 }
            }
        };
   });

这个解决方案可以让你传递一个名称生成器表达式给指令,并避免锁定他正在使用的模式替换。

我最初对这个解决方案也有困难,因为它没有显示在标记中使用它的例子,所以这里是我如何使用它。

<form name="theForm">
    <div ng-repeat="field in fields">
        <input type="number" ng-form name="theInput{{field.id}}" ng-model="field.value" dynamic-form-name dnfn-name-expression="'theInput' + field.id">        
    </div>
</form>

我有一个更完整的工作在github例子。




如果你使用ng-repeat $索引就像这样工作

  name="QTY{{$index}}"

   <td>
       <input ng-model="r.QTY" class="span1" name="QTY{{$index}}" ng-            
        pattern="/^[\d]*\.?[\d]*$/" required/>
        <span class="alert-error" ng-show="form['QTY' + $index].$error.pattern">
        <strong>Requires a number.</strong></span>
        <span class="alert-error" ng-show="form['QTY' + $index].$error.required">
       <strong>*Required</strong></span>
    </td>

我们必须以ng模式显示ng-show

   <span class="alert-error" ng-show="form['QTY' + $index].$error.pattern">
   <span class="alert-error" ng-show="form['QTY' + $index].$error.required">



在使用ng-repeat指令的标签内部使用ng-form指令。 然后可以使用由ng-form指令创建的作用域来引用通用名称。 例如:

    <div class="form-group col-sm-6" data-ng-form="subForm" data-ng-repeat="field in justificationInfo.justifications"">

        <label for="{{field.label}}"><h3>{{field.label}}</h3></label>
        <i class="icon-valid" data-ng-show="subForm.input.$dirty && subForm.input.$valid"></i>
        <i class="icon-invalid" data-ng-show="subForm.input.$dirty && subForm.input.$invalid"></i>
        <textarea placeholder="{{field.placeholder}}" class="form-control" id="{{field.label}}" name="input" type="text" rows="3" data-ng-model="field.value" required>{{field.value}}</textarea>

    </div>

信贷: http://www.benlesh.com/2013/03/angular-js-validating-form-elements-in.html : http://www.benlesh.com/2013/03/angular-js-validating-form-elements-in.html




基于pkozlowski.opensource的answer ,我添加了一种方法来获得也适用于ngMessages动态输入名称。 注意ng-form元素上的ng-init部分以及furryName的使用。 furryName成为包含input name属性的变量值的变量name

<ion-item ng-repeat="animal in creatures track by $index">
<ng-form name="animalsForm" ng-init="furryName = 'furry' + $index">
        <!-- animal is furry toggle buttons -->
        <input id="furryRadio{{$index}}"
               type="radio"
               name="{{furryName}}"
               ng-model="animal.isFurry"
               ng-value="radioBoolValues.boolTrue"
               required
                >
        <label for="furryRadio{{$index}}">Furry</label>

        <input id="hairlessRadio{{$index}}"
               name="{{furryName}}"
               type="radio"
               ng-model="animal.isFurry"
               ng-value="radioBoolValues.boolFalse"
               required
               >
        <label for="hairlessRadio{{$index}}">Hairless</label>

        <div ng-messages="animalsForm[furryName].$error"
             class="form-errors"
             ng-show="animalsForm[furryName].$invalid && sectionForm.$submitted">
            <div ng-messages-include="client/views/partials/form-errors.ng.html"></div>
        </div>
</ng-form>
</ion-item>



Related