Dynamische Formulare mit createElement und appendChild
Marcus
- javascript
Hallo,
ich bin gerade über ein kleines Problem gestolpert und hoffe von jemandem einen geeigneten Tipp zu bekommen.
Ich versuche folgendes:
Bei einem Eingabeformular soll der Nutzer beliebig viele Zeilen mit jeweils 2 Input-Felder zusätzlich hinzufügen können.
Da alles in einer Tabelle angeordert ist mache ich das nach folgendem Schema:
Zunächst wird in der Tabelle mit 'insertRow' eine neue Zeile generiert und anschließend mit 'createElement' die jeweiligen Tabellenfelder generiert. Dann über 'innerHTML' die Input-Felder in die Tabellenfelder geschrieben und zu letzt alles mit Hilfe von 'appendChild' in das 'table'-Objekt eingefügt. Funktioniert soweit auch Prima.
Jetzt tut sich allerdings ein Browserproblem auf - mit dem Internetexplorer funktioniert alles reibungslos, will heißen die Formularfelder "funktionieren" korrekt. Beim Mozilla Firefox sieht die Sache allerdings anders aus: hier werden die neu generierten Zeilen und Felder zwar gleichermaßen angezeigt, beim Absenden des Formulars aber nicht berücksichtigt. Will heißen: die Daten aus den neu generierten Input-Feldern werden NICHT mit übertragen.
Folgende Teillösung des Problems konnte ich bereits erarbeiten:
Wenn ich neu angelegten Input-Felder testweise mit Daten belege und dann mit 'appendChild' nicht im Tabellenfeld einhänge, sondern stattdessen im Formular-Objekt - dann sendet auch der FireFox die Daten korrekt. Allerdings werden die Inputs dann in beiden Browsern nicht mehr angezeigt (und sind somit auch schlecht zu bearbeiten).
Hier noch der Quelltext des Javascripts:
function crow(mytab) {
if (mytab == "THon") { art = "TECHON"; }
if (mytab == "TTec") { art = "TECMIET"; }
f = document.getElementById('TecForm'); // ID des Formulars
t = document.getElementById(mytab); // ID der Tabelle
Z = document.getElementById(mytab + 'Count').value; // Zählt die Anzahl der vorhandenen Tabellenzeilen
TR = t.insertRow(Z);
document.getElementById(mytab + 'Count').value = parseInt(Z) + 1;
mTD = document.createElement("td");
mTD.innerHTML = "<b>" + Z + "</b>";
TR.appendChild(mTD);
mTD2 = document.createElement("td");
mTD2.innerHTML = "<input id='" + mytab + Z + "titel' name='" + art + Z + "titel' value='hallo' style='width:300px'>";
TR.appendChild(mTD2);
inp1 = document.getElementById(mytab + Z + "titel");
f.appendChild(inp1);
// mTD2.appendChild(inp1);
mTD3 = document.createElement("td");
mTD3.innerHTML = "<input id='" + mytab + Z + "' name='" + art + Z + "betrag' value='' style='width:60px' onBlur='neueSumme(""+ mytab +"");' onKeyUp='checkKomma(""+ mytab + Z + "");'> Euro";
TR.appendChild(mTD3);
/* inp2 = document.getElementById(art + Z + "betrag");
f.appendChild(inp2); */
}
Die Count-Variablen nutze ich um mit den Felder anschließend noch arbeiten zu können. (Die Beträge werden automatisch summiert, wenn man Daten eingibt.)
Ich hoffe irgendjemand hat vielleicht eine Idee, wie ich das ganze doch noch Browser-kompatibel hinbekomme.
Gruß, marcus
Hi,
Ich hoffe irgendjemand hat vielleicht eine Idee, wie ich das ganze doch noch Browser-kompatibel hinbekomme.
Wenn ich inputs mit dom erzeuge hat Mozilla keine Probleme:
<html>
<head>
<script type="text/javascript">
var inpNam = "inp";
var cnt = 0;
function goForIt() {
cnt ++;
var inp = document.createElement("input");
inp.style.width = "100px";
inp.setAttribute("type","text");
inp.setAttribute("name",inpNam + cnt);
br = document.createElement("br");
document.getElementById("dynform").appendChild(inp);
document.getElementById("dynform").appendChild(br);
}
</script>
</head>
<body>
<form Name="feld" id="dynform">
<input type="submit" value="Send">
<input type="button" value="New" onclick="goForIt()">
<br><br>
</form>
</body>
</html>
ansonsten schau doch mal im dominspector (Mozilla), ob Deine dynamischen elemente ueberhaupt als solche in der Domhirarchie auftauchen.
Gruesse, Joachim
Also, ich habe mal nachgeschaut: Wenn ich im Mozilla die 'Page Info' abrufe und unter 'Forms' nachsehe, fehlen die dynamisch erzeugten in der Tat.
(Was halt auch daran liegt, dass ich meine Inputs mit appendChild nicht dem Form angehängt hatte).
Die Lösung von Joachim funktioniert, doch stellt sich mir hier die Frage, wie baue ich jetzt zusätzlich die Tabellenfelder rundherum?
Als erstes werde ich jetzt mal versuchen die inputs ebenfalls mit createElement zu erzeugen, und nicht über innerHTML abzukürzen.
Und 1 oder 2 weitere neue Ideen hab ich auch noch.
Ich werd meine Fortschritte mal posten, hoffe aber auch weiterhin auch gute Ratschläge ;)
Erstmal dank an Joachim.
Gruss, marcus.
Nun gut - weitere Ergebnisse:
1.
Meinen ursprünglichen Quelltext habe ich so verändert, dass die Inputs ebenfalls über createElement erzeugt wurden, aber weiterhin in die Tabelle eingehängt wurden (anstatt ins Formular).
Resultat: keins - Mozilla erkennt die inputs immernoch nicht als Teil des Formulars
2.
Habe versucht, die inputs in das Formular einzuhängen und dann mit 'outerHTML' die tabellezeile/feld zu ergänzen. Wie gehabt erkennt der Mozilla die inputs dann als teil des Formulars, aber die Angabe outerHTML scheint überhaupt keine Wirkung zu haben, ganz egal was ich da hineinschreibe.
3.
Habe versucht, die inputs doppelt einzuhängen, sie also per appendChild einmal in den Baum des Formulars und ausserdem in die Tabelle mit einzufügen. Ebenfalls kompletter Humbug (die letzte Einweisung ist dann das Resultat, aber ohne die Wirkung der ersten und somit bin ich wieder am Anfang). Ihr seht ich bin verzweifelt!
Die Schwierigkeit in meinem Fall ist halt, dass ich in einem Formular eine Haupttabelle habe, in der 2 weitere Tabellen verschachtelt sind.
Und in jeder dieser beiden Unter-Tabellen soll der Nutzer neue Zeilen hinzufügen können.
Wäre es nicht so kompliziert wäre die Lösung von Joachim oder auch meine ursprüngliche ausreichend gewesen.
Hat noch jemand was, das mir Hoffnung gibt?
(Meine Notfall-Variante wäre, 2 Inputs zu erzeugen, eins eingehängt in die Tabelle, eins eingehängt ins Formular (als Hidden), und bei OnSubmit die Values von dem einem zum anderen zu schieben. Aber das finde ich irgendwie grotesk, oder doch nicht?)
Hi,
Du hast irgendwo Fehler drinne, schau Dir mal an das mit tabelle an:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<script type="text/javascript">
var inpNam = "inp";
var cnt = 0;
function goForIt() {
cnt ++;
var inp = document.createElement("input");
inp.style.width = "100px";
inp.setAttribute("type","text");
inp.setAttribute("name",inpNam + cnt);
tr = document.createElement("tr");
td1 = document.createElement("td");
td2 = document.createElement("td");
txt = document.createTextNode(inpNam + cnt);
td1.appendChild(txt);
td2.appendChild(inp);
tr.appendChild(td1);
tr.appendChild(td2);
document.getElementById("test").appendChild(tr);
}
</script>
</head>
<body>
<form Name="feld" id="dynform">
<table id="test" cellspacing="0" cellpadding="0" border="1">
<tr>
<td colspan="2">
<input type="submit" value="Send">
<input type="button" value="New" onclick="goForIt()">
</td>
</tr>
</table>
</form>
</body>
</html>
Gruesse, Joachim
Hallo,
die TRs sind Kinder vom tbody und nicht vom table.
Gruß, Jürgen
Hi,
die TRs sind Kinder vom tbody und nicht vom table.
Du hast voellig Recht, ich vergesse das immer. Also noch den tbody einziehen und ihm die id geben, dann hat auch IE keine Probleme.
Gruesse Joachim
Hallo,
var inp = document.createElement("input");
inp.style.width = "100px";
inp.setAttribute("type","text");
inp.setAttribute("name",inpNam + cnt);
ich habe die Erfahrung gemacht, dass nicht alle Browser alle Attribute dynamisch akzeptieren.
inp.setAttribute("name",...);
und
inp.name=...
funktionieren zwar im Moz, nicht aber im IE. Daher greife ich auf dynamisch erzeugte inputs mit getElementsByTagName zu.
Gruß, Jürgen
Hi,
ich habe die Erfahrung gemacht, dass nicht alle Browser alle Attribute dynamisch akzeptieren.
inp.setAttribute("name",...);
Afaik immer dann, wenn der direkte Zugriff auf die Eigenschaft moeglich ist, z.B: backgroundColor. Mit name und type hat zumindestens IE6 kein Problem (Moz sowieso nicht).
Gruesse, Joachim
Hallo,
bei folgender Seite
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Test</title>
<script type="text/javascript">
function start() {
var ipt = document.createElement("input");
ipt.size=2; //geht in IE, MOZ, Opera
//ipt.name="x_y_z"; //geht in MOZ, Opara
ipt.setAttribute("name","x_y_z",true);
ipt.onclick="alert(this.name)"; //geht in Opera
ipt.value="F4"; //geht in IE, MOZ, Opera
document.getElementsByName("frm")[0].appendChild(ipt) ;
if (document.frm.x_y_z) alert(document.frm.x_y_z.value);
}
</script>
</head>
<body onload="start()">
<form name="frm" action="" method="" target="">
<input type="Text" name="i_n_p" value="F1" size="" maxlength="" onclick="alert(this.name)">
</form>
</body>
</html>
liefert der MOZ/Firefox ein alert, der IE6 bleibt stumm. Der onclick in "F4" geht auch im Firefox nicht.
Gruß, Jürgen
Hi,
ipt.onclick="alert(this.name)"; //geht in Opera
das ist auch falsch, so rufst Du den alert - Du willst aber nur einen Zeiger setzen. Versuch mal:
ipt.onclick=function(){alert(this.name)};
Gruesse, Joachim
Hallo,
stimmt. Aber der alert kommt im IE trotzdem nicht. Meine Vermutung ist, dass der IE dynamisch erzeugte Elemente nicht über ihren Namen ansprechen kann, denn der onklick zeigt ja, dass der Name gesetzt ist.
Gruß, Jürgen
Hi,
stimmt. Aber der alert kommt im IE trotzdem nicht.
um so erstaunlicher ist, dass ein Versand der Form dann aber brav alle get-parameter anhaengt - auch die dynamisch erzeugten.
Naja, man wird da wohl mit Unzulaenglichkeiten leben muessen, hier hilft als workaround eine "kuenstliche" Referenz:
document.frm.x_y_z = ipt;
Gruesse, Joachim
Hallo Joachim,
Naja, man wird da wohl mit Unzulaenglichkeiten leben muessen, hier hilft als workaround eine "kuenstliche" Referenz:
document.frm.x_y_z = ipt;
der Trick funktioniert, danke.
Gruß, Jürgen
PS: Schade, dass Marcus verschwunden ist. Ich hoffe, wir haben ihn nicht vergrault.
Hallo ihr beiden!
Nein, ihr habt mich nicht vergrault - hatte nur gestern leider keine Zeit mehr mich mit dem Thema auseinander zu setzen.
Heute jedoch habe ich das getan.
Der Tipp mit dem tbody war in der Tat Gold wert, da er das zu letzt gepostete Beispiel-Script zum funktionieren brachte.
Als ich das jedoch in meinen Quelltext eingebettet hatte, wollte es immernoch nicht funktionieren.
Nach einiger Zeit am grübeln habe ich dann den Fehler entdeckt.
Folgende Konstruktion war meine Ausgangsbasis:
<table>
<form>
<tr><td> <table> [...] <tbody id="Hier sollten die Inputs rein"> [.. ] </table> </td></tr>
<tr><td> <table> [...] <tbody id="Hier sollten andere Inputs rein"> [.. ] </table> </td></tr>
</form>
</table>
Die beiden 'table' Elemente in denen ich meine Manipulationen machen wollte, waren zwar innerhalb des Form-Tags notiert, jedoch offenbar nicht dem form zugeordert sondern der äußeren Tabelle, welche ja noch ausserhalb des 'form' notiert war.
Nachdem ich also die 'Form' Tags ausserhalb der äußeren Tabelle positioniert hatte funktionierte auf einmal alles Prima!
Ich danke euch beiden, für die guten Ideen.
Hallo nochmal.
Ich habe gerade noch etwas entdeckt.
Am Anfang hatte ich doch in meinem Quelltext eine Variante,
die in die per createElement erzeugten TDs den Inhalt und auch die Input-Felder direkt über td.innerHTML reingeschrieben hat.
Nachdem ich nun mein Problem gelöst hatte, habe ich auch das nocheinmal ausprobiert und siehe da - es funktioniert.
Die Inputs werden registriert und AUCH EVENTS wie OnBlur oder OnKeyUp (andere habe ich nicht getestet) funktionieren wunderbar.
Meiner Meinung nach erspart einem das eine Menge Quelltext, da man nicht jedes Feld erzeugen muss und dann mühsam eine Eigenschaft nach der anderen erzeugen und einhängen muss.
Auf jedenfall bin ich jetzt sehr glücklich und kann weiterbasteln :)
Gruß, Marcus.
Hallo,
<table>
<form>
<tr><td> <table> [...] <tbody id="Hier sollten die Inputs rein"> [.. ] </table> </td></tr>
<tr><td> <table> [...] <tbody id="Hier sollten andere Inputs rein"> [.. ] </table> </td></tr>
</form>
</table>
das ist so nicht erlaubt. In der Tabelle dürfen nur Tabellenelemente stehen. Leg das <form> und </form> nach außen, dann stimmt es.
Gruß, Jürgen