0

I am trying to pull all the forms for my page from a json object with values to plug into the ng-required, max-values min-values and type fields. But these values aren't being inserted into the dom. How would I go about repeating over a number of input elements and control whether or not they were text boxes or file uploads and whether or not they are required? I did up a fiddle based on what I was hoping to accomoplish but cant figure out why this doesn't work. see the jsfiddle.

HTML

<form novalidate name="form1" ng-controller="step1">
    <div ng-repeat="field in json">
        <label>
            {{field.label}}

        </label>
        <input type="field.type" ng-model="field.model">
    </div>
</form>

Javascript

function step1($scope) {
$scope.json = [
    { 
        "error": "Must be more then 3 letters", 
        "label": "store Name 1",
        "model": "storeName"
    },
    {
        "error": "Must be more then 3 letters", 
        "label": "store Name 1",
        "model": "storeName"
    }
];
}
2
  • Your example json here doesn't have type property. Your jsfiddle has 'required' property, which you mention in the intro. You state that it 'doesn't work' but it's not clear in what way it's not working. In particular, attribute interpolation requires double braces i.e. "{{field.required}}" -- but fixing that doesn't change anything -- because the form isn't code to do anything with that property, as you haven't accounted for form validation in your markup. Commented Jan 30, 2014 at 23:41
  • Additionally, you cannot dynamically change the type of an input tag without writing a complex custom directive that removes and adds elements, etc. see: stackoverflow.com/a/14954923/149060 including both input elements that you ng-show or not based on the value is one way to get the intended behavior. Commented Jan 30, 2014 at 23:47

1 Answer 1

1

Setting input type dynamically is bit tricky, but may be achived with custom directive that appends input to the DOM. From the other hand, inserting inputs to the form dynamically from custom directive you can't enjoy things like myForm.myInput.$error.requred. Besides of it you probably want to add error message and some styling to invalid inputs, therefore you need some CSS.

Here is an example of dynamic form created from JSON with ng-required, ng-maxlength and ng-minlength enabled:

Plunker: http://plnkr.co/edit/F7BGq0sfSLvKE48eDTzQ?p=preview

HTML

<!DOCTYPE html>
<html ng-app="demo">

  <head>
    <script src="http://code.angularjs.org/1.2.10/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="demoController">
    <form name="demoForm">
      <div demo-directive ng-repeat="input in inputs"></div>
    </form>
  </body>

</html>

CSS

.error .required,
.error .minlength,
.error .maxlength {
  display: none;
}

.ng-invalid-required + .error .required,
.ng-invalid-minlength + .error .minlength,
.ng-invalid-maxlength + .error .maxlength {
  display: inline;
}

.ng-invalid {
  outline: 1px solid red;
}

.error {
  color: red;
}

JavaScript

angular.module('demo', []).
  controller('demoController', function($scope) {
    $scope.inputs = [{
      inputType: 'checkbox',
      name: 'f1',
      checked: true,
      label: 'input 1',
      required: true
    }, {
      inputType: 'text',
      name: 'f2',
      value: 'some text 1',
      label: 'input 2',
      required: true
    }, {
      inputType: 'file',
      name: 'f3',
      label: 'input 3'
    }, {
      inputType: 'text',
      name: 'f4',
      value: 'some text 2',
      label: 'input 2',
      min: 2,
      max: 15
    }];
  }).
  directive('demoDirective', function($compile) {
    return {
      template: '<div><label>{{input.label}}: </label></div>',
      replace: true,
      link: function(scope, element) {
        var el = angular.element('<span/>');
        switch(scope.input.inputType) {
          case 'checkbox':
            el.append('<input type="checkbox" name="{{input.name}}" ng-model="input.checked" ng-required="{{input.required}}"/><span class="error"><span class="required">Required!</span></span>');
            break;
          case 'text':
            el.append('<input type="text" name="{{input.name}}" ng-model="input.value" ng-required="{{input.required}}" ng-minlength="{{input.min}}" ng-maxlength="{{input.max}}" /><span class="error"><span class="required">Required!</span><span class="minlength">Minimum length is {{input.min}}!</span><span class="maxlength">Maximum length is {{input.max}}!</span></span>');
            break;
          case 'file':
            el.append('<input type="file" name="{{input.name}}" ng-model="input.value" ng-required="{{input.required}}"/><span class="error"><span class="required">Required!</span></span>');
            break;
        }
        $compile(el)(scope);
        element.append(el);
      }
    }
  });
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.