验证AngularJS中指令的字段

时间:2014-03-27 20:29:47

标签: angularjs

我正在尝试将输入和一些标记包装到AngularJS指令中。

然而,据说这些字段总是经过验证,不应该是。

请查看我的示例@ http://plnkr.co/edit/TivmuqQI4Y5K56gwcadW

这里是那些不想看Plunker的人的代码

我的指示

app.directive('myInput', function() {
  return {
    restrict: 'E',
    require: '^ngModel',
    templateUrl: 'form_control.html',
    scope: {
      label: '@',
      placeholder: '@',
      name: '@',
      form: '=',
      ngModel: '=ngModel'
    },
  }
});

这是我的模板

<div class="form-group" ng-class="{'has-error': form.{{name}}.$invalid && form.{{name}}.$dirty, 'has-success': form.{{name}}.$valid }">
<label for="{{name}}" class="col-sm-2 control-label">{{label}}</label>
<div class="col-sm-10">
    <input type="{{type}}" class="form-control col-sm-10" id="{{name}}" name="{{name}}" ng-model="ngModel" placeholder="{{placeholder}}" ng-maxlength="10" ng-required="true">
</div>
</div>

这是我的index.html

<my-input ng-model="website.url" name="url" label="URL" placeholder="http://example.com" form="form"></my-input>

即使模板中的输入是必需的,该字段也会被验证,如果它是空的,则不应该是该字段。

我做错了什么?

1 个答案:

答案 0 :(得分:0)

必填字段在DOM加载时立即无效,因为它们在有值之前无效。

此外,在您的plunker中,顶部输入为绿色,有一个有效的错觉,而较低的输入为红色,表示无效。

你不能这样做......

<div class="form-group" ng-class="{'has-error': form.{{name}}.$invalid && form.{{name}}.$dirty, 'has-success': form.{{name}}.$valid }">

问题在于表单名称字段。当你这样做时......

<input type="{{type}}" class="form-control col-sm-10" id="{{name}}" name="{{name}}" ng-model="ngModel" placeholder="{{placeholder}}" ng-maxlength="10" ng-required="true">

name =&#34; {{name}}实际上会在表单对象中编译为name {{name}}。 〔实施例:

{{name}}: Constructor$dirty: false
          $error: Object
          $formatters: Array[1]
          $invalid: true
          $isEmpty: function (value) {
            $modelValue: undefined
            $name: "{{name}}"
            $parsers: Array[1]...

这是从您的plunker。使用console.log($ scope.form)并查看对象。 在$ error下你会发现有两个输入这个表单引用,并且它们都不是名为&#39; url&#39;的预期输入,它们实际上是&#39;标题&#39;输入和您的指令输入&#39; {{name}}&#39;如此处所见......

form: Constructor
  $addControl: function (control) {
    $dirty: false
    $error: Object...
      $name: "title"...
      $name: "{{name}}"

这是一个分叉的plunker,我已经设置了console.log表格

Plunker

这表明该表单不知道任何&#39; url&#39;输入。要解决此问题,您可以为输入名称字段编写自定义指令。或者只使用我在下面写的那个。

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 } // if no ngModel exists for this element

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

      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.myName )){ // should be in format "wordcharacters/wordcharacters"
      throw myNameError + "Formatting should be \"inputName/formName\" but is " + attrs.myName
    }
  }

  function assignInputNameToInputModel(inputName, ngModel){
    ngModel.$name = inputName // adds string to ngModel.$name variable.
  }

  function addInputNameToForm(formName, ngModel, scope){
    scope[formName][ngModel.$name] = ngModel; return // add input name and input object.
  }

  function findForm(formName, ngModel, scope){
    if( !scope ){ // ran out of scope before finding scope[formName]
      throw myNameError + "<Form name=" + formName + "'> element 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
  }
});

// DIRECTIVE NOTES:
// This directive is used by simply including the following HTML element:
// <input my-name="email/profileForm">.
// In the example above, the input name is "email" and the form name
// that this input would be attached to would be named "profileForm"
// Like this...
// <form name="profileForm">
//   <input my-name="email/profileForm">
// </form>
// Notice this "/" dividing the input name from the form name.  This directive uses the '/'
// to separate the input name from the form name.
// Although it has not been tested yet, this directive should work with multi nested forms
// as well, as the recursive search only looks for the form name that was passed in, inwhich
// to bind the ngModel to.
// In this example, other form names would be skipped.
// <form name="profileForm">
//   <form name="miniFormOne">
//      <form name="miniFormTwo">
//        <input my-name="email/profileForm">
//      </form>
//   </form>
// </form>
// The above example may not be the best behavior, but was just added as an example.

使用此指令,您可以像这样使用嵌套指令输入

<input type="{{type}}" class="form-control col-sm-10" id="{{name}}" my-name="{{ variableName  + '/' + yourformnamevariable  }}" ng-model="ngModel" placeholder="{{placeholder}}" ng-maxlength="10" ng-required="true">

myName指令将得到:&#34; url / form&#34;在你的情况下,然后它将添加$ name变量,它将是&#39; url&#39;到用于THAT输入的ngModel,以及搜索名为&#34; form&#34;的表单的范围。并将ndModel附加到THAT表单。该指令使用&#39; /&#39;分开名字。搜索是递归的,并且会一直运行,直到找到表单名称或错误消息为止。

当然,当您创建动态输入名称时,如何调用

formName.dynamicInputName $有效吗?因为你不知道动态输入名称是什么!!!

所以使用表单。{{name}}。$ invalid&amp;&amp; form。{{name}}。$ dirty不起作用,除非你这样做......

form.$valid && form.$dirty

但是这对每个人的输入都不起作用。你可以找出自己的方法......

我在输入

中使用另一个指令

然后在我的错误中,我只是在需要ngModel之后听取ngModel,你现在可以调用ngModel。$ invalid然后设置一个变量来改变CSS。如果我有时间,我会制作一个jsFiddle并将其链接到底部。但是,您可以使用类input.ng-invalid {border-color:red;输入将是红色的,直到它们有效。

如果这不清楚,请再问一些问题......我们会得到它。

希望这个有用的