1

I have a form with currently one field, which has few validation rules:

<form name="my_form" novalidate ng-controller="FormController">
    <label>Your Name:</label>
    <input type="text"
           name="name"
           placeholder="Your Name"
           ng-model="form.name"
           ng-minlength="3"
           ng-maxlength="20"
           unique
           required />
    <button ng-click="submitForm()">Submit</button>
    <div class="error"
           ng-show="my_form.isSubmitted"
           ng-messages="my_form.name.$error">
        <div ng-messages-include="errors.html"></div>
    </div>
</form>

My field is validated against:

  • Min. length;
  • Max. length;
  • It's required
  • And must be unique (custom validation rule)

I'm using ng-messages to display error messages near input field. Here is my errors.html template:

<div ng-message="required">This field is required.</div>
<div ng-message="minlength">This field is too short.</div>
<div ng-message="maxlength">This field is too long.</div>
<div ng-message="unique">The value of this field must be unique.</div>

The validation should be started only after 'Submit' button is pressed (submitForm() function sets my_form.isSubmitted flag to true and my error div is displayed)

Here is my js code:

var app = angular.module('formValidation', ['ngMessages']);

app.controller('FormController', function($scope) {
  $scope.submitForm = function() {
    $scope.my_form.isSubmitted = true;
  };
});

app.directive('unique', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, ele, attrs, ctrl) {
      var names = ['Dmitry', 'Alexander', 'Elizabeth'];
      ctrl.$parsers.push(function(value) {
        if (names.indexOf(value) > -1) {
          ctrl.$setValidity('unique', false);
          return false;
        }
        ctrl.$setValidity('unique', true);
        return true;
      });
    }
  };
);

Everything works fine, but what I want to do now is to hide errors if the field is modified after errors were shown (until submit button will be pressed again).

The first idea came to my mind is to add another condition to ng-show directive of error div to check if corresponding field is updated and if it is, errors should not be shown. Something like:

<div class="error"
       ng-show="!my_form.name.isUpdated && my_form.isSubmitted"
       ng-messages="my_form.name.$error">
    <div ng-messages-include="errors.html"></div>
</div>

So, on button click I can set isUpdated flag of all form fields to false and on input update can set it to true. But this solution seems to me far from elegant. I'm sure there is a better way to achieve this behaviour. Any ideas?

2
  • Maybe ng-change directive on the input to let the form know one of the values has changed? Commented Nov 8, 2015 at 17:05
  • Form should not know when the value of field is changed. But when the value of some field is changed, I need to hide only corresponding to this field error div. When submit button is clicked, errors (if such exist) should apear again. Commented Nov 8, 2015 at 17:13

1 Answer 1

1

My current solution (probably not the best one):

<input type="text"
           name="name"
           placeholder="Your Name"
           ng-model="form.name"
           ng-minlength="3"
           ng-maxlength="20"
           unique
           updatable
           required />
    <button ng-click="submitForm()">Submit</button>
    <div class="error"
           ng-show="!my_form.name.isDirty && my_form.isSubmitted"
           ng-messages="my_form.name.$error">
        <div ng-messages-include="errors.html"></div>
    </div>

I added new directive updatable to my field and updated the show condition for error div:

ng-show="!my_form.name.isDirty && my_form.isSubmitted"

The directive:

app.directive('updatable', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, ele, attrs, ctrl) {
      ele.bind('input', function() {
        scope.$apply(function() {
          ctrl.isDirty = true;
        });
      );
    }
  };
});

And a small update of submitForm function which now sets isDirty flag of my field(s) to false:

$scope.submitForm = function() {
    $scope.my_form.isSubmitted = true;
    $scope.my_form.name.isDirty = false;
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.