<!DOCTYPE html>
<html>

  <head>
    <link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
    <script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
    <script src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
     <script src="app.js"></script>
  </head>

  <body ng-app="plunker" >
  <div ng-controller="DynamicFormController">
   <h3>Dynamic Forms with Validation in AngularJS</h3>
 
 <form name="myForm" class="form-horizontal" role="form" ng-submit="submitForm()">
 <div ng-repeat="field in entity.fields">    
  <ng-form name="form">
    <!-- TEXT FIELDS -->
    <div ng-if="field.type=='text'" class="form-group">
      <label class="col-sm-2 control-label">{{field.label}}</label>
      <div class="col-sm-6">
        <input type="{{ field.type }}" dynamic-name="field.name" id="{{field.name}}" data-ng-model="field.data"  class="form-control" required/>
         <span  data-ng-show=" {{'form.'+field.name+'.$dirty && form.'+field.name+'.$error.required'}}">Required!</span>
      </div>
    </div>

    <!-- EMAIL FIELDS -->
    <div ng-if="field.type=='email'" class="form-group">
      <label class="col-sm-2 control-label">{{field.label}}</label>
      <div class="col-sm-6">
        <input type="{{ field.type }}" dynamic-name="field.name" data-ng-model="field.data" class="form-control" required/>
         <span data-ng-show=" {{'form.'+field.name+'.$dirty && form.'+field.name+'.$error.required'}}">Required!</span>
         <span data-ng-show=" {{'form.'+field.name+'.$dirty && form.'+field.name+'.$error.email'}}">Not email!</span>
      </div>
    </div>

    <!-- PASSWORD FIELDS -->
    <div ng-if="field.type=='password'" class="form-group" >
      <label class="col-sm-2 control-label">{{field.label}}</label>
      <div class="col-sm-6">
        <input type="{{ field.type }}" dynamic-name="field.name" data-ng-model="field.data" ng-minlength={{field.min}} ng-maxlength={{field.max}} class="form-control" required/>
         <span data-ng-show=" {{'form.'+field.name+'.$dirty && form.'+field.name+'.$error.required'}}">Required!</span>
         <span data-ng-show=" {{'!form.'+field.name+'.required && (form.'+field.name+'.$error.minlength || form.'+field.name+'.$error.maxlength)' }}">Passwords must be between 8 and 20 characters.</span>
        </div>
    </div>

  <!-- SELECT FIELDS -->
    <div ng-if="field.type=='select'" class="form-group" >
      <label class="col-sm-2 control-label">{{field.label}}</label>
      <div class="col-sm-6">
        <select data-ng-model="field.data" ng-options="option.name for option in field.options" class="form-control" required ></select>
      </div>      
    </div>

    <!-- RADIO FIELDS -->
    <div ng-if="field.type=='radio'" class="form-group">
      <label class="col-sm-2 control-label">{{field.label}}</label>
      <div class="col-sm-6">
           
        <div class="checkbox" ng-repeat="option in field.options" >
                  <label>                
            <input type="radio" data-ng-model="field.data"  name="taskGroup"  id="{{option.name}}" value="{{option.id}}">{{option.name}}
          </label>
                </div>
      </div>
    </div>

    <!-- CHECKBOX FIELDS -->
    <div ng-if="field.type=='checkbox'" class="form-group" >
      <label class="col-sm-2 control-label">{{field.label}}</label>
      <div class="col-sm-6">        
               <div class="checkbox" ng-repeat="option in field.options" >
                  <label>
                    <input type="checkbox" data-ng-model="option.data"  name="taskGroup"  id="{{option.name}}" value="{{option.id}}" >{{option.name}}
                  </label>
                </div>
      
      </div>
    </div>

  </ng-form>

 </div>


  <br/>
  <br/>
  <button ng-disabled="myForm.$invalid" type="submit" id="submit">Submit</button>
  <br/>
  <br/>
  <pre>{{entity|json}}</pre>
   <br/>
       
 </form>
 </div>
  </body>

</html>
var app = angular.module('plunker',[]);

app.controller('DynamicFormController', function ($scope, $log) {
    

 
    // we would get this from the api
    $scope.entity = {
      name : "Test", 
      fields :
        [
          {type: "text", name: "firstname", label: "Name" , required: true, data:""},
          {type: "radio", name: "color_id", label: "Colors" , options:[{id: 1, name: "orange"},{id: 2, name: "pink"},{id: 3, name: "gray"},{id: 4, name: "cyan"}], required: true, data:""},
          {type: "email", name: "emailUser", label: "Email" , required: true, data:""},
          {type: "text", name: "city", label: "City" , required: true, data:""},
          {type: "password", name: "pass", label: "Password" , min: 6, max:20, required: true, data:""},
          {type: "select", name: "teacher_id", label: "Teacher" , options:[{name: "Mark"},{name: "Claire"},{name: "Daniel"},{name: "Gary"}], required: true, data:""},
          {type: "checkbox", name: "car_id", label: "Cars" , options:[{id: 1, name: "bmw"},{id: 2, name: "audi"},{id: 3, name: "porche"},{id: 4, name: "jaguar"}], required: true, data:""}
        ]
      };

      $scope.submitForm = function(){
        $log.debug($scope.entity);
      }
})

  .directive("dynamicName",function($compile){
    return {
        restrict:"A",
        terminal:true,
        priority:1000,
        link:function(scope,element,attrs){
            element.attr('name', scope.$eval(attrs.dynamicName));
            element.removeAttr("dynamic-name");
            $compile(element)(scope);
        }
    }
})