Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm trying to validate dynamic form input generated using a directive and isolate scopes. Outside the directive I've got the main form, and inside the ng-repeat I'm trying to use ng-form, but it doesn't ever show the error messages. Initially I had the ng-form on ng-repeat, but figured that wouldn't work since it was out of scope in the directive, so placed it on the parent div of the directive, but still doesn't show validation on invalid email.

Form with ng-repeat and field directive

<form name="mainForm" 
      role="form" 
      ng-controller="WizardFormController as wizFormCtrl" 
      ng-submit="submit( mainForm.$valid )"
      novalidate>

      <div ng-repeat="field in panel.form_fields">

           <form-field field="field" 
                       model="models[field.field_name]" ng-form="subForm">
           </form-field>

      </div>

      <div class="form-group clearfix">
      <button class="btn btn-primary pull-right" 
              ng-click="update( models )"
              ng-disabled="mainForm.$invalid">Save Progress</button>

      </div>

</form>

Form Field Directive

<div class="form-group" ng-form="subForm">

    <label for="{{field.field_name}}">{{field.field_label}}</label>

    <input type="text"
       class="form-control"
       id="{{field.field_id}}"
       name="{{field.field_name}}"
       ng-model="model">

     <div ng-show="subForm[field.field_name].$dirty &&
              subForm[field.field_name].$invalid">Invalid:

    <span ng-show="subForm[field.field_name].$error.email">This is not a valid email.</span>
    </div>

</div>

Looks like it should work looking at the generated markup indicating the field is ng-valid:

<div class="form-group ng-scope ng-dirty ng-valid-required ng-valid ng-valid-email" 
     ng-form="subForm">

Is it just how I'm accessing subForm:

subForm[field.field_name].$dirty

UPDATE I found the work around for this and answered it below, see here

share|improve this question
    
Can you post your directive JS code as well as a demo fiddler/plnkr? –  Beyers Sep 3 at 21:51

2 Answers 2

use this as a Form Field Directive:

<div class="form-group" ng-form="subForm">

    <label for="{{field.field_name}}">{{field.field_label}}</label>

    <input type="email"
       class="form-control"
       id="formid"
       name="formname"
       ng-model="model">

     <div ng-show="subForm.formname.$dirty &&
              subForm.formname.$invalid">Invalid:

    <span ng-show="subForm.formname.$error.email">This is not a valid email.</span>
    </div>

</div>

ng-form itself handle field name. you cant put name="{{field.field_name}}" like this.

share|improve this answer
    
Hi, what if I can't avoid this since we're generating large amounts of forms using a form-field directive and json, so the only hard-coded bit is the type, and we provide all the different html input types and select as templates. Is there another way to do this maybe not using ngForm that was just a way I found through the AngularJS docs and some tutorials. –  mtpultz Sep 3 at 18:52
    
i dont think there is an alternative for this. dynamically generated form field can only be validated through this. –  Mukund Kumar Sep 3 at 19:00
    
It does validate in the parent form properly, just not on a specific input allowing me to show input errors. I'll keep digging and see if there is solution of some sort. Thanks –  mtpultz Sep 3 at 19:05
    
just put type="email" for validate email form. i think it will work properly for specific input field also. just use edited code –  Mukund Kumar Sep 3 at 19:14
1  
Hey, I found a solution. This particular issue has a few different solutions that have been amalgamated over the last 2 years that can be found on GitHub (github.com/angular/angular.js/issues/1404). The easiest solution to drop in is this one: plnkr.co/edit/hSMzWC?p=preview. Just add it as a dependency and the code in the example above just works. –  mtpultz Sep 3 at 20:00
up vote 0 down vote accepted

The solution for this issue is apparently in the works, and has been an issue for 2+ years. Add your vote to it on GitHub! The easiest solution to implement and arguably the best solution can be found here with credit to Thinkscape, and I've copied it below.

  angular.module('interpol', [])

  .config(function($provide) {

    $provide.decorator('ngModelDirective', function($delegate) {
      var ngModel = $delegate[0], controller = ngModel.controller;
      ngModel.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
        var $interpolate = $injector.get('$interpolate');
        attrs.$set('name', $interpolate(attrs.name || '')(scope));
        $injector.invoke(controller, this, {
          '$scope': scope,
          '$element': element,
          '$attrs': attrs
        });
      }];
      return $delegate;
    });

    $provide.decorator('formDirective', function($delegate) {
      var form = $delegate[0], controller = form.controller;
      form.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
        var $interpolate = $injector.get('$interpolate');
        attrs.$set('name', $interpolate(attrs.name || attrs.ngForm || '')(scope));
        $injector.invoke(controller, this, {
          '$scope': scope,
          '$element': element,
          '$attrs': attrs
        });
      }];
      return $delegate;
    });
  })

  .run(function($rootScope) {
    $rootScope.models = [{
      value: 'foo'
    },{
      value: 'bar'
    },{
      value: 'baz'
    }];
});

I just dropped it in, marked it as a dependency, and the form in my question works.

Cheers

share|improve this answer
    
Though how this actually works is a mystery I'm too new to AngularJS. Anyone interested in giving a high-level description of the above solution? –  mtpultz Sep 3 at 20:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.