Generate dynamic form input fields and collect field data in an array

41,971

Solution 1

Right now you are iterating $scope.fields. When you are adding a new field you push an empty object into $scope.fields, but every input's ng-model points to $scope.table.fields (which is non-existing until first input writes to it - then it will hold a string variable).

For this simple use case you could try:

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

  $scope.table = { fields: [] };

  $scope.addFormField = function() {
    $scope.table.fields.push('');
  }

  $scope.submitTable = function() {
    console.log($scope.table);
  }

});

And:

<input ng-repeat="field in table.fields track by $index" type='text' ng-model='table.fields[$index]' placeholder='Field:'>

Demo: http://plnkr.co/edit/6iZSIBa9S1G95pIMBRBu?p=preview

Solution 2

Take a look at this

Working Demo

html

<body>
<div ng-app=''>
    <div ng-controller="questionCtrl">
        <div>
            <ul>
                <li ng-repeat="elemnt in questionelemnt">

                    <div>
                        <div id={{elemnt.id}} style="display:inline" >
                            <span  ng-model="elemnt.question" ng-hide="editorEnabled" ng-click="editorEnabled=true">
                                {{elemnt.question}}
                            </span>
                            <div  ng-show="editorEnabled">
                                <input  ng-model="elemnt.question" ng-show="editorEnabled" >
                                <button href="#" ng-click="editorEnabled=false">Done editing</button>
                            </div>
                        </div>
                        <div style="display:inline">
                            <span>
                                <input type="text" ng-model="elemnt.answer" placeholder="Answer" required/>
                            </span>
                        </div>

                        <span ng-hide="elemnt.length == 1">

                             <button ng-click="questionelemnt.splice($index, 1)">Remove</button>

                        </span>
                    </div>
                    <hr/>
                </li>
                <li>
                     <button ng-click="addFormField($event)">Add</button>
                </li>
            </ul>
        </div>
        <div>
            <button ng-click="showitems($event)">Submit</button>
        </div>
        <div id="displayitems" style="visibility:hidden;">
            {{questionelemnt}}
        </div>
    </div>
</div>
</body>

script

function questionCtrl($scope) {
    var counter = 0;
    $scope.questionelemnt = [{
        id: counter,
        question: 'Question-Click on me to edit!',
        answer: ''
    }];

    $scope.addFormField = function ($event) {
        counter++;
        $scope.questionelemnt.push({
            id: counter,
            question: 'Question-Click on me to edit!',
            answer: ''
        });
        $event.preventDefault();
    }

    $scope.showitems = function ($event) {
        $('#displayitems').css('visibility', 'none');
    }
}
Share:
41,971
r.sendecky
Author by

r.sendecky

I am a network engineer working for a financial company in Sydney. In my spare time I enjoy programming Ruby and learning Haskell. Also, I love hunting, camping and mat/ring fighting (Ju-Jitsu, Boxing)

Updated on October 24, 2020

Comments

  • r.sendecky
    r.sendecky over 3 years

    I am stuck with this little task. I need to generate form input fields dynamically by clicking 'add' button on the form. The form is supposed to create DB table schema. So every input field is a DB table field name.

    I am OK generating the fields dynamically but have trouble with gathering the actual data.

    <form ng-controller="NewTableCtrl" ng-submit="submitTable()">
      <input type='text' ng-model='table.title' placeholder='Title:'>
      <input ng-repeat="field in fields" type='text' ng-model='table.fields' placeholder='Field:'>
      <div>
        <button type='submit'>Submit</button>
        <button ng-click="addFormField()">Add</button>
      </div>
    </form>
    

    .. and the controller

    .controller('NewTableCtrl', function($scope) {
      $scope.fields = [];
      $scope.table = {};
    
      $scope.addFormField = function () {
        $scope.fields.push({});
      }
    
      $scope.submitTable = function () {
        console.log($scope.table);
      }
    });
    

    Looks simple. When I click 'Add' button it generates the new input field but it does it with the same model object (obveously). And that's where my misunderstanding lies. I thought that if I declare $scope.fields = [];in the controller then repeating field data will just go into the array. But it just echoes the input in every repeating input field. I understand now that this is how it is supposed to be with two way binding.

    The reason I thought like this is by the analogy with an ordinary form submission where the repeating input field names become an array in the URL encoded form data.

    So how do I solve this? The server needs to get an array of fields like this: fields: [field1, field2 ...] Do I need to generate input fields with different scope variable for each field? How do I do this?

    Is this more complex then I thought and it needs to be a directive? If yes, please, show me how to do this.

    Thanks.