4

I have to do form validation for multiple forms which have to be created dynamically. I have created the forms dynamically by using ng-repeat but I am not able to access that form in controller.

Please check the code:

 <button ng-click="navigate()">Next</button>
   <div ng-repeat="service in services">
     <ng-form name="mainform">
        <div ng-repeat="spec in service.products">
           <ng-form name="subform">
               <input type="text" name="{{spec.name}}" ng-model="spec.value">
               <span ng-show="subform[spec.name].$invalid">please enter</span>
           </ng-form>
        </div>
    </ng-form> 
  </div >

It is working fine, but I need to check whether at least one of mainform's subforms is valid or not after clicked on next button so I have tried to access this in controller like this:

 $scope.navigate=function(){
     console.log($scope.mainform.subform);
     console.log($scope.subform);
 }

but I am getting undefined for both console logs. How can I access multiple dynamically created forms in the controller?

4
  • Shouldn't it be <ng-form [name="mainform"]> ? Commented Dec 6, 2016 at 19:07
  • What exactly do you want to do with these forms in controller? Commented Dec 6, 2016 at 19:34
  • I want to check in controller that at least any one of the mainform has all valid data in subform Commented Dec 6, 2016 at 19:38
  • This probably is one of the reasons HTML disallows nested forms.... Commented Dec 6, 2016 at 21:09

3 Answers 3

1

What exactly do you want to do with forms in controller?

Looks like you don't need it.

You have forms hierarchy. Pseudocode:

ng-form mainForm
  ng-form subFormOne
  ng-form subFormTwo

If subFormOne or subFormTwo is invalid then mainForm will be invalid too. If all sub forms are valid then mainForm will be valid too. You will check only mainForm.$valid in your code.

If you need to style it somehow you I recommend you to use css there. ngForm directive adds classes to the element. You can use .ng-form selector in css to add styles to your form. For example:

.ng-form.ng-invalid {
  background-color: #ff0000;
} 

Here is plunkr example.

8
  • controller file how to do that ? ....I have tried like this but getting error ... Commented Dec 6, 2016 at 19:44
  • $scope.navigate=function(){console.log($scope.mainform.$invalid)} Commented Dec 6, 2016 at 19:45
  • I added the plunkr example Commented Dec 6, 2016 at 19:48
  • If you have form name "mainForm" you have to use: console.log($scope.mainForm.$inva‌​lid) Commented Dec 6, 2016 at 19:54
  • in your code mainform is not a ng-repeat one ...it is kind of static ...but if you look at my code there is two form one is mainform another one is subform both will be created using ng-repeat ...you code won't work when there is both forms are dynamically created ... Commented Dec 6, 2016 at 20:14
1

The logs show undefined because because the ng-repeat directive creates child scopes and the forms are put on those child scopes.

Create a form at the top level, above the ng-repeat:

<button ng-click="navigate()">Next</button>

<!-- ADD top form above ng-repeat -->
<ng-form name=top>
    <div ng-repeat="service in services">
        <ng-form name="mainform_{{$index}}">
            <div ng-repeat="spec in service.products">
                 <ng-form name="subform_{{$index}}">
                     <input name="{{spec.name}}" ng-model="spec.value">
                 </ng-form>
            </div>
        </ng-form> 
    </div>
</ng-form>

Then forms inside the ng-repeat will be visible:

$scope.navigate=function(){
     console.log($scope.top);
     console.log($scope.top.mainform_0);
     console.log($scope.top.mainform_0.subform_0);
};

The DEMO on PLNKR

0

I would use $index from ng-repeat or something makes it unique.

UPDATE: 12/6/2016 Based on the comment.

plnkr of deeply nested dynamic forms and validation

<button ng-click="navigate()">Next</button>
<div class="outer" ng-repeat="service in services" ng-init="serviceSuffix=$index;serviceForm = 'form' +serviceSuffix">
  <h2>{{service.serviceName}} id= {{service.id}} {{serviceForm}}</h2>

  <ng-form name="{{serviceForm}}">
    <button ng-click="isValidForm(serviceSuffix)">Is Outer valid</button>
    <div class="inner" ng-repeat="spec in service.products" ng-init="specSuffix = serviceSuffix+'_'+$index; specForm = 'form' +specSuffix; ">
      <h2>{{spec.specName}} id={{spec.id}} {{specForm}}</h2>
      <ng-form name="{{specForm}}">
        <input required type="text" name="{{spec.specName}}" ng-model="spec.value">
        <span ng-show="this[specForm][spec.specName].$invalid">please enter</span>
        <button ng-click="isValidForm(specSuffix)">Is Inner valid</button>
      </ng-form>
    </div>
  </ng-form>
</div>

To access nth form in your controller.

  $scope.isValidForm = function(suffix) {
    alert('form '+suffix+' valid='+$scope['form' +suffix].$invalid)
  };
6
  • ya I agree . but how to check this in controller ? Commented Dec 6, 2016 at 19:33
  • Giving one example but it would be best if you come with how and where do you want to check a particular form. Commented Dec 6, 2016 at 19:40
  • when i click on next button I need to check whether any one the main form is valid or not Commented Dec 6, 2016 at 19:41
  • You can access any of the forms using the form suffix. Also you need to know the name of the form before checking valid or invalid. So if you know the form suffix Next button can check valid or invalid. Commented Dec 6, 2016 at 20:51
  • I don't want to have these many buttons in this html...I need only one button that is there in top (navigate) . Commented Dec 7, 2016 at 9:09

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.