2014-04-30 4 views
7

Utknąłem z tym małym zadaniem. Potrzebuję dynamicznie generować pola wprowadzania formularzy, klikając przycisk "Dodaj" w formularzu. Formularz ma utworzyć schemat tabeli bazy danych. Zatem każde pole wejściowe jest nazwą pola tabeli DB.Generowanie dynamicznych pól wprowadzania formularzy i zbieranie danych pola w tablicy

Generuję pola dynamicznie, ale mam problemy ze zbieraniem rzeczywistych danych.

<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> 

.. a kontroler

.controller('NewTableCtrl', function($scope) { 
    $scope.fields = []; 
    $scope.table = {}; 

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

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

Wygląda proste. Kiedy klikam przycisk "Dodaj", generuje nowe pole wejściowe, ale robi to z tym samym obiektem modelu (obraźliwie). I tutaj leży moje nieporozumienie. Pomyślałem, że jeśli zadeklaruję $scope.fields = []; w kontrolerze, powtarzające się dane pola zostaną wprowadzone do tablicy. Ale to tylko echo wejścia w każdym powtarzalnym polu wejściowym. Rozumiem teraz, że tak właśnie powinno być z dwukierunkowym wiązaniem.

Powodem, dla którego tak pomyślałem, jest analogia ze zwykłym przesyłaniem formularzy, w którym powtarzające się nazwy pól wejściowych stają się tablicą w zakodowanych adresach danych formularzy.

Jak rozwiązać ten problem? Serwer musi uzyskać tablicę takich pól: fields: [field1, field2 ...] Czy muszę generować pola wejściowe z różnymi zmiennymi zasięgu dla każdego pola? Jak mam to zrobic?

Czy to jest bardziej złożone niż myślałem i musi to być dyrektywa? Jeśli tak, proszę, pokaż mi, jak to zrobić.

Dzięki.

Odpowiedz

11

W tej chwili trwa iteracja $scope.fields. Kiedy dodajesz nowe pole, wciskasz pusty obiekt do $scope.fields, ale każdy model wejściowy ng wskazuje na $scope.table.fields (który jest nieistniejący, dopóki pierwsze wejście do niego nie napisze - wtedy będzie utrzymywał zmienną łańcuchową).

Na tym prostym przypadku użycia można spróbować:

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

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

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

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

}); 

oraz:

<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

+0

Dziękuję. To jest miłe. Dowiedziałem się też o 'track by'. Czy korzystanie z 'track by' jest zawsze korzystne ze względu na wydajność? –

+0

Nie ma za co :) W bardziej złożonych sytuacjach tak (http://www.bennadel.com/blog/2556-using-track-by-with-ngrepeat-in-angularjs-1-2.htm). W takim przypadku możliwe jest posiadanie wielu pól o tej samej wartości ciągu, w przeciwnym razie otrzymasz: "Duplikaty w repeater nie są dozwolone. Użyj wyrażenia "track by", aby określić unikatowe klucze. " – tasseKATT

+0

Wiem, że to stary wątek, wciąż trzeba o coś zapytać. jak wyświetlić dane w formularzu utworzonym za pomocą powyższego kodu? Każda pomoc byłaby doceniana. –

2

Spójrz na tego

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> 

skrypt

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'); 
    } 
} 
0

Variation roztworu tasseKATTs użyciu HashMap zamiast tablicy. To pozwala mi mieć ładny obiekt JSON, który mogę zaimplementować, aby zbudować filtr zapytań.

http://plnkr.co/edit/CArP3Lkmn7T5PEPdXgNt?p=preview

<!DOCTYPE html> 
<html> 

    <head> 
    <script data-require="[email protected]*" data-semver="1.3.0" src="//code.angularjs.org/1.3.0/angular.js"></script> 
    <link rel="stylesheet" href="style.css" /> 
    <script src="script.js"></script> 
    <style> 
     div{ margin: 1em;} 
     input{margin-left:1em;} 
    </style> 
    </head> 

    <body ng-controller="myCtrl"> 

    <h2>Using a filter map tied to ng-model to create a filter object</h2> 

    <div ng-repeat="field in fields"> 
     {{field}}<input ng-model=filters[field] /> 
    </div> 

    <hr> 
    <h3>Filter</h3> 
    {{filters}} 

    <script> 

     var app=angular.module("app",[]); 

     app.controller("myCtrl",function($scope){ 
     $scope.filters={}; 
     $scope.fields=["name","address","phone","state"]; 
     }); 

     angular.bootstrap(document,["app"]); 

    </script> 

    </body> 

</html>