Formular dynamisch erweitern.

südpol

Erfahrenes Mitglied
Hi,

ich möchte gerne ein formular dynamisch erweitern. Sprich wenn jemand auf einen button klickt sollen weitere Felder erscheinen. Klickt er noch mal kommen noch mehr etc.

Es soll also z. B. ein input feld da stehen darunter ein button <noch eins> und nach jedem klick wird ein weiteres feld hinzugefügt, dass als prfix im namen einfach eine zahl hat die um 1 hochgezählt wird...

Wie geht das? hat jemand zufällig ein gute Anleitung oder ein speispielscript zur hand?

P. S. komme aus der php - Ecke und habe wenig Ahnung von javascript - muss ich leider zugeben...

Gruß
 

Sven Mintel

Mitglied
Beispiel:
Code:
<html>
<head>
<title>Test</title>
<script type="text/javascript">
<!--
function clone_this(objButton)
{
if(objButton.parentNode)
    {
    tmpNode=objButton.parentNode.cloneNode(true);
    objButton.form.appendChild(tmpNode);
    for(j=0;j<objButton.form.lastChild.childNodes.length;++j)
        {
        if(objButton.form.lastChild.childNodes[j].type=='text')
            {
            objButton.form.lastChild.childNodes[j].value='';
            break;
            }
        }
    objButton.value="entfernen";
    objButton.onclick=new Function('f1','this.form.removeChild(this.parentNode)');
    }
}
//-->
</script>
</head>
<body>
<form>
 <div>
  <input type="text"size="20"name="textfeldname[]"><br>
  <input type="button"value="noch eins"onclick="clone_this(this)">
 </div>
</form>
</body>
</html>
Erläuterung:
Der Button und das Textfeld stehen in einem <div>(kann auch was anderes sein...span bspw)
Beim Aufruf wird der Funktion der Button als Objekt übergeben...dadurch hat man Zugriff auf alle seine Eigenschaften.

if(objButton.parentNode)
Abfrage, ob der Button einen Elternknoten hat...in DOM-Browsern ist dies der Fall...der Elternknoten ist das <div>

tmpNode=objButton.parentNode.cloneNode(true);
Von diesem Elternknoten wird eine Kopie erstellt

objButton.form.appendChild(tmpNode);
diese Kopie wird ans Ende des Formulars gehängt

Code:
for(j=0;j<objButton.form.lastChild.childNodes.length;++j)
        {
        if(objButton.form.lastChild.childNodes[j].type=='text')
            {
            objButton.form.lastChild.childNodes[j].value='';
            break;
            }
        }
...der Inhalt des grad erstellten Textfeldes wird gelöscht... der wurde nämlich mitgeklont :)

Danach habsch noch als Feature das Ändern des angeklickten Buttons eingefügt...sein Wert wird auf "entfernen" geändert...wenn man jetzt draufklickt, wird dieser Button incl. des dazugehörigen Textfeldes wieder gelöscht.
(kannst du natürlich rausnehmen, wenn du es nicht brauchst)

Auf das Durchnummerieren der Textfelder hab ich verzichtet....das wäre unnützer Mehraufwand.
In PHP kannst du durch die Klammer in "textfeldname[]" auch so bequem auf die Textfelddaten zugreifen.

Testbeispiel
 

südpol

Erfahrenes Mitglied
... wenn wir uns jemals treffen geb ich dir einen aus! Super Anleitung super Beispiel! ... das man textfelder als array speichern kann wusste ich auch noch nicht *grübel* ich dachte, dass hatte ich schon mal getestet...

Eine, für dich vermutlich einfache, Frage verbleibt noch. Was muss ich an dem Skript ändern um das neue Textfeld an die Stelle zu bekommen an der bis jetzt der "noch ein Feld" Button war. Wenn das geht bin ich fast restlos glücklich bzw. ab dann sollte ich alle Änderungen durch try and error rausfinden können...

noch mal vielen vielen Dank!
 

Sven Mintel

Mitglied
Das ginge z.B. so:
Code:
<html>
<head>
<title>Test</title>
<script type="text/javascript">
<!--
function clone_this(objButton)
{
    /**
      *  Das div, in welchem sich das erste input befindet, wird geclont
      **/
    
    tmpNode = objButton.form.elements[0].parentNode.cloneNode(true);
    
    
    /**
      *  das geklonte div wird vor dem Button eingefügt
      *  Syntax...Elternknoten.insertBefore(einzufügenderKnoten,KnotenVorDemEingefügtWerdenSoll);
      **/
    
    objButton.form.insertBefore(tmpNode,objButton);
    
    
    /**  Den Wert des eingefügten inputs wieder löschen
      * previousSibling ist der vorige Knoten eines Typs vor einem anderen Knoten...
      * in diesem Fall das neue div vor dem Button....firstChild wieder das erste Kindelement darin...also das input
      **/
      
    objButton.previousSibling.firstChild.value='';
    
}
//-->
</script>
</head>
<body>
<form>
 <div><input size="20" name="textfeldname[]" type="text"></div>
 <input value="noch eins" onclick="clone_this(this)" type="button">
</form>
</body>
</html>
 

südpol

Erfahrenes Mitglied
VIELEN DANK SOWEIT SCHON MAL!

das sieht alles nicht so schwer aus - aber so richig gut anpassen funktioniert bei mir leider noch nicht. Könnt ihr mir zu dem Thema DHTML ein gutes Buch empfehlen. Das Thema scheint eine sehr gute Ergänzung für meine php - Seiten zu sein.

Wenn ihr Lust habt könnt ihr mir - solange das Buch auf dem Postweg ist :D - ja noch ein paar Tipps geben. Ich muss die Funktion nun nämlich noch erweitern *heul* :eek:

Ich habe ein ganz langes Formular, welches sich dynamisch mit Daten füllt. Ganz am Ende des Formulars soll nun ein Button hin der das Eingeben eines weiteren Datensatzes ermöglicht. Die Probleme vor denen ich stehe sind folgende:
1. ich muss eine ganze Tabelle inkl. Formularelemente einfügen
2. das ganze soll wie von euch schon gezeigt per klick auf einen Button immer weiter erweitert werden können.

Vielen Dank für eure Tipps!
 

Sven Mintel

Mitglied
Naja... ob Tabelle oder Textfeld ist da egal....
klone die Tabelle mitsamt Inhalt, und hänge sie ans Ende ran.... für JS macht das keinen Unterschied :)
 

Sven Mintel

Mitglied
Wenn du eine Tabbelle Klonen willst, dann musst die Tabelle ansprechen.
Zum ranhängen musst du...wenns ans Ende des Formular soll...das Formular ansprechen.
 

südpol

Erfahrenes Mitglied
Hi,

ich hoffe ich nerve nicht zusehr. Ich habe das ganze jetzt mal 'selber' versucht. Ist zwar sehr primitiv (vermutlich). Allerdings funktioniert es nicht. Ihr als Profis müsst bestimmt nich lange suchen um den Fehler zu finden. Ich hänge an dieser Stelle mal wieder.

So - sollte - der Ablauf sein: html Teil in ein div - Tag packen und über css "verstecken". Dieses Element soll dann zukünftig durch eine funktion geclont und vor dem Button wieder eigefügt werden. (so ist die Funktion auch noch in anderen Teilen einsetzbar und muss nicht angepasst werden :) -> man ist ja faul *g*)

So dachte ich könnte das js aussehen:
PHP:
function clone_this(button, objid)
{
  var clone_me = document.getElementById(objid).cloneNode(true);
  document.getElementById(button).insertBefore(clone_me, document.getElementById(button));
}
diese funktion wird dann im head eingefügt. Das html zeugs könnte dann so aussehen:

PHP:
<div style="visibility:hidden; display:none">
<div "dolly">
  <table>
    <tr>
      <td>test</test>
      <td><input type="text" name="test[]"></input></td>
    </tr>
      <td>test2</test>
      <td><input type="text" name="test2[]"></input></td>
    </tr>
  </table>
</div>
</div>

<div class="new_passage">
  <input value="mehr" onclick="javascript:clone_this(this, 'new_passage');" type="button"></input>
</div>

Leider funktioniert das nicht - hat jemand einen Tipp bzw. einen verbesserungsvorschlag, damit das ganze funktioniert?

DANKE!
 

Quaese

Moderator
Moderator
Hi,

mit folgender Funktion clonest Du die Tabelle, die sich innerhalb des DIVs befindet. Es ist zu
beachten, dass sich zwischen dem DIV- und dem TABLE-Tag kein Zeichen befindet. Dieses
würde in einigen Browsern als firstChild-Objekt erkannt werden. Damit würde nicht die
Tabelle, sondern das Zeichen gecloned werden.
Code:
function clone_this(button, objid){
    // Tabelle innerhalb des DIVs mit ID "new_passage" clonen
    // Achtung: Es dürfen keine Zeichen zwischen dem DIV- und dem TABLE-Tag stehen!
    var clone_me = document.getElementById(objid).firstChild.cloneNode(true);

    // Im Parent-DIV vor dem Kindknoten "button" einhängen
    button.parentNode.insertBefore(clone_me, button);
}
Deinen bisherigen Code müsstest Du folgendermassen abändern:
HTML:
<div style="visibility:hidden; display:none">
<div id="new_passage"><table name="cloneTable">
    <tr>
      <td>test</test>
      <td><input type="text" name="test[]"></input></td>
    </tr>
      <td>test2</test>
      <td><input type="text" name="test2[]"></input></td>
    </tr>
  </table>
</div>
</div>

<div>
  <input value="mehr" onclick="javascript:clone_this(this, 'new_passage');" type="button"></input>
</div>
Ich hoffe, das hilft Dir weiter.

Ciao
Quaese