Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
560 views
in Technique[技术] by (71.8m points)

forms - implementing a directive to exclude a hidden input element from validation ($addControl issue)

I'm creating a directive to exclude a hidden input element from validation: http://plnkr.co/edit/Vnwvq2AT7JpgTnoQwGh9?p=preview

app.directive('shownValidation', function() {
    return {
      require: '^form',
      restrict: 'A',
      link: function(scope, element, attrs,form) {
        var control;

        scope.$watch(attrs.ngShow,function(value){
          if (!control){
            control = form[element.attr("name")];
          }
          if (value == true){
            form.$addControl(control);
          }else{
             form.$removeControl(control);
          }
        });
      }
    };
  });

The idea here is if the element is hidden, I will remove the control from the Form so that it will not affect the other input validity. It works fine when I call form.$removeControl(control);, you can test that in the demo by removing the firstname and clicking on the button to hide the field.

But when I click the button again, the form validity is still true even though the firstname is invalid (empty)

I also tried adding form.$setValidity(form.$valid && control.$valid) => the validity state is updated as expected but when I type into the firstname, the validity is still false.

My question is how to solve this problem? Thanks for any replies.

Update:

Thanks to @Michael's answer. Here is the working solution:

app.directive('shownValidation', function() {
  return {
    require: '^form',
    restrict: 'A',
    link: function(scope, element, attrs, form) {
      var control;

      scope.$watch(attrs.ngShow, function(value) {
        if (!control) {
          control = form[element.attr("name")];
        }
        if (value == true) {
          form.$addControl(control);
     //Add a forEach to manually update form validity.Thanks to @Michael's answer
          angular.forEach(control.$error, function(validity, validationToken) {
            form.$setValidity(validationToken, !validity, control);
          });
        } else {
          form.$removeControl(control);
        }
      });
    }
  };
});

Working plunk

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If the control is removed angular updates the validity (from the sources):

  form.$removeControl = function(control) {
    if (control.$name && form[control.$name] === control) {
      delete form[control.$name];
    }
    forEach(errors, function(queue, validationToken) {
      form.$setValidity(validationToken, true, control);
    });

    arrayRemove(controls, control);
  };

If you add the control angular did not update the validity (from the sources):

  form.$addControl = function(control) {
    // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
    // and not added to the scope.  Now we throw an error.
    assertNotHasOwnProperty(control.$name, 'input');
    controls.push(control);

    if (control.$name) {
      form[control.$name] = control;
    }
  };

so we have to do this manually. I guess this way:

if (value == true){
    form.$addControl(control); 
    angular.forEach(control.$error, function(validity, validationToken) {
       form.$setValidity(validationToken, !validity, control);
    });
   }else{
    form.$removeControl(control);
   }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...