Dynamic form validation in angularJS not working

I've created a dynamic form and add attributes ng-required

dynamically to my controls. but now it doesn't work.

This is my JS:

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

    app.controller('main', function($scope){ 
      $scope.Control={};
     $scope.Attributes =[
   {
     "Name":"FirstName",
     "Required":true
   },
   {
     "Name":"LastName",
     "Required":false
   },
   {
     "Name":"Email",
     "Required":true
   },
   {
     "Name":"Age",
     "Required":false
   }];

        $scope.submitForm = function(isValid) {

            // check to make sure the form is completely valid
            if (isValid) { 
                alert('our form is amazing');
                alert($scope.Control[1]);  // to check correct index
            }else{
              return;
            }

        };
    });

      

And my HTML:

<html>

<head lang="en">

  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" />
  <script src="app.js"></script>

</head>

<body ng-app="birthdayToDo" ng-controller="main">
  <form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate>
    <table>
      <tr ng-repeat="attribute in Attributes">
        <td>{{attribute.Name}}</td>
        <td>
          <input type="text" name="Control[$index]" ng-model="Control[$index]" ng-required="{{attribute.Required}}" />
        </td>
        <td>
         <p ng-show="userForm.Control[$index].$error.required">{{attribute.Required == "true" && attribute.Name+' Required' || ''}}</p>
        </td>
      </tr>
    </table>
    <input type="submit" value="Save" />
  </form>
</body>

      

Plunger link

I want to show an error message when submitting or changing the value of a textbox.

But when I do the same with a static form, it works. worker plucker

+3


source to share


1 answer


Dynamic control names and form validation don't work that well with older angular versions (<1.3.x). And add to that, you have a very old version of angular (1.0.3). If you are upgrading to 1.3.x angular you can easily achieve this with some changes (some of which you will need):

1) As @dfsq mentioned, you need to provide a boolean value for the bound border property with ng, otherwise you will end up setting "true" / "false" truths on the controls and that will do whatever is necessary.

2) Use ng-attr-name

to provide interpolated dynamic names. It will automatically expand to name the attribute.

3) With 1.3 the form controller is setting a property $error.required

with the same name as the control and there are some more special properties that it populates. You can always track the total number of errors required withform.$error.$required.length

4) Don't use an index to set the ng-model, use your own attribute name to make it more readable and easier to manage.

5) You can also use one-time bind ( ::

)
to avoid unwanted hours, example field names, display names, required attributes, which if they don't change lists.

6) You can use special properties of the form controller to control your actions and other ways and interactions as needed. Here's an example demo that uses only a small subset of what the form controller provides.



View:

<form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate>
    <table>
      <tr ng-repeat="attribute in Attributes">
        <td>{{::attribute.Name}}</td>
        <td>
          <input type="text" ng-attr-name="{{::attribute.Name}}" ng-model="Control[attribute.Name]" ng-required="::attribute.Required" />
        </td>
        <td>
          <p ng-if="userForm[attribute.Name].$error.required" class="error">{{attribute.Name }} Required</p>
        </td>
      </tr>
    </table>
    <input type="submit" value="Save" ng-disabled="userForm.$invalid"/>{{Control}}
  </form>

      

Controller:

 /* Set proper boolean values to Required*/
 $scope.Attributes = [{
    "Name": "FirstName",
    "Required": true
  }, {
    "Name": "LastName",
    "Required": false
  }, {
    "Name": "Email",
    "Required": true
  }, {
    "Name": "Age",
    "Required": false
  }];

  $scope.submitForm = function(isValid) {

    // check to make sure the form is completely valid
    if (isValid) {
     /*Now control will have proper property names with respective ngmodel names*/
      console.log($scope.Control); 
    } else {
      return;
    }

  };

      

Demo version

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

app.controller('main', function($scope) {

  $scope.Control = {};

  //Set boolean values to Required
  $scope.Attributes = [{
    "Name": "FirstName",
    "Required": true 
  }, {
    "Name": "LastName",
    "Required": false
  }, {
    "Name": "Email",
    "Required": true
  }, {
    "Name": "Age",
    "Required": false
  }];

  $scope.submitForm = function(isValid) {


    if (isValid) {
      alert('our form is amazing');
      console.log($scope.Control); /*Use Controle object which has proper property names to reflect respective ngModel*/
    } else {
      return;
    }

  };
});
      

.error {
  color: red;
}
input.ng-invalid {
  border: 2px solid red;
}
      

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
<div ng-app="birthdayToDo" ng-controller="main">
  <form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate>
    <table>
      <tr ng-repeat="attribute in Attributes">
        <td>{{::attribute.Name}}</td>
        <td>
          <input type="text" ng-attr-name="{{::attribute.Name}}" ng-model="Control[attribute.Name]" ng-required="::attribute.Required" />
        </td>
        <td>
          <p ng-if="userForm[attribute.Name].$error.required" class="error">{{attribute.Name }} Required</p>
        </td>
      </tr>
    </table>
    <input type="submit" value="Save" ng-disabled="userForm.$invalid"/>{{Control}}
  </form>
</div>
      

Run codeHide result


+5


source







All Articles