Dynamické přidávání elementů formuláře
Občas se může hodit vytvořit dynamický formulář, jehož elementy jsou doplňovány až po vyvolání nějaké události uživatelem.
Článek se bude zabývat pouze vytvořením INPUTů a SELECTů z formuláře, ale obecně platí pro jakýkoli element.
Občas může nastat situace, kdy je potřeba vypsat formulář, který se bude dynamicky měnit v závislosti na uživatelově rozhodnutí.
Přesně k takovému formuláři nám může pomoci javascript, pomocí něhož jednoduše vytvoříme nový element a umístíme na příslušné místo:
var num_of_lines = 1;
function plus(element){
var x = document.getElementById( element );
var input = document.createElement('input'); input.setAttribute('name', 'input[]' ); input.setAttribute('value', 'text' );
var option1 = document.createElement('OPTION'); option1.setAttribute('value', 'prvni');
var option2 = document.createElement('OPTION'); option2.setAttribute('value', 'druha');
var option3 = document.createElement('OPTION'); option3.setAttribute('value', 'treti');
var option4 = document.createElement('OPTION'); option4.setAttribute('value', 'ctvrta');
var txt1 = document.createTextNode("Krátký text"); option1.appendChild(txt1);
var txt2 = document.createTextNode("Dlouhý text"); option2.appendChild(txt2);
var txt3 = document.createTextNode("Celé číslo"); option3.appendChild(txt3);
var txt4 = document.createTextNode("Desetinné číslo"); option4.appendChild(txt4);
var select = document.createElement('select'); select.setAttribute('name', 'select[]' );
var text = document.createTextNode('Možnost: '); var p = document.createElement('span'); p.setAttribute('id', 'span_' + num_of_lines ); var br = document.createElement('br');
select.appendChild(option1); select.appendChild(option2); select.appendChild(option3); select.appendChild(option4);
p.appendChild(text); p.appendChild(input); p.appendChild(select); p.appendChild(br);
x.appendChild(p);
num_of_lines ++; }
function minus(element){ if( num_of_lines < 1 ) return false; var d = document.getElementById( element ); var olddiv = document.getElementById( 'span_' + num_of_lines ); num_of_lines--; d.removeChild(olddiv); } plus('new_sab'); plus('new_sab'); plus('new_sab');
Uvedený příklad si postupně rozebereme a vysvětlíme.
Základem celého příkladu jsou dvě funkce:
- funkce pro přidávání řádku formuláře
- funkce pro vymazání řádku formuláře
Obě funkce jsou volány po kliknutí na příslušný odkaz a je jim předáno jako parametr ID elementu, do kterého budou přidávat nebo mazat.
Nejprve trochu teorie:
createElement
CreateElement slouží, jak název napovídá, pro vytvoření elementu. Můžeme jím velice jednoduše vytvořit například TAG P, BR, nebo jakýkoli jiný jiné.
V našem příkladu potřebujeme vytvořit tagy SELECT, s ním související OPTION, a INPUT.
Funkce se volá velice jednoduše:
1 2 3 |
var input = document.createElement('input'); var option1 = document.createElement('OPTION'); var select = document.createElement('select'); |
Takto jednoduše vytvoříme elementy, se kterými můžeme dále pracovat.
SetAttribute
SetAttribute slouží pro přidávání atributů k vytvořeným elementům nebo tagům.
Tato funkce má dva parametry, první je jméno atributu a druhý je jeho hodnota. Můžeme tak snadno přidat k našemu inputu hodnotu name nebo value. Popřípadě tuto funkci můžeme zavolat vícekrát a přidat atributů víc:
1 2 |
input.setAttribute('name', 'input[]' ); input.setAttribute('value', 'text' ); |
createTextNode
CreateTextNode slouží pro vytvoření textového popisku. Prostě textu.
S textem můžeme potom dále pracovat a umístit jej například jako hodnotu do jiného elementu:
1 2 |
var txt1 = document.createTextNode("Krátký text"); option1.appendChild(txt1); |
appendChild
Funkce pro připojení potomka. U jejího použití je důležité si dávat pozor na správné připojování. Připojovat potomky můžeme pouze do párových tagů, takže například do INPUTU žádného potomka připojit nemůžeme. Na rozdíl od toho do SELECTu ano:
1 2 3 4 |
select.appendChild(option1); select.appendChild(option2); select.appendChild(option3); select.appendChild(option4); |
removeChild
Vymazání elementu. Použití je obdobné jako u appendChild.
Formulář
Nyní vám popíši jak funguje můj příklad, který jsem uvedl výše.
Existují zde dvě funkce. Funkce plus() a funkce minus(). Funkce plus() slouží pro přidání řádku do formuláře a funkce minus() pro jeho vymazání.
Dále zde existuje globální proměnná pojmenovaná num_of_lines, do které si dynamicky ukládám počet vytvořených řádků ve formuláři, abych si podle ní mohl snadno vytvářet unikátní ID elementů pro mazání.
U obou funkcí je vstupní parametr název elementu, ID elemntu, do kterého se bude přidávat, nebo ze kterého se bude mazat.
Funkce plus(element){}
Na začátku funkce si vytvořím proměnnou, ve které si uložím objekt elementu, předaný jako parametr, abych s ním mohl později pracovat. Přidávat do něj elementy.
1 |
var x = document.getElementById( element ); |
Nyní můžu začít vytvářet nový řádek formuláře. Jako první si vytvořím input a přidám do něj atribut name:
1 2 |
var input = document.createElement('input'); input.setAttribute('name', 'input[]' ); |
Další element, který budu potřebovat, je SELECT a několik OPTIONů. Do jednotlivých OPTIONů si přidám textové popisky a value hodnoty. Navíc budu potřebovat name hodnotu u SELECTU:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var option1 = document.createElement('OPTION'); option1.setAttribute('value', 'prvni'); var option2 = document.createElement('OPTION'); option2.setAttribute('value', 'druha'); var option3 = document.createElement('OPTION'); option3.setAttribute('value', 'treti'); var option4 = document.createElement('OPTION'); option4.setAttribute('value', 'ctvrta'); var txt1 = document.createTextNode("Krátký text"); option1.appendChild(txt1); var txt2 = document.createTextNode("Dlouhý text"); option2.appendChild(txt2); var txt3 = document.createTextNode("Celé číslo"); option3.appendChild(txt3); var txt4 = document.createTextNode("Desetinné číslo"); option4.appendChild(txt4); var select = document.createElement('select'); select.setAttribute('name', 'select[]' ); |
Nyní by jsem mohl tyto dva elementy již přidat pomocí appendChild do elementu předaného jako parametr, ale ještě si oba atributy obalím elementem span, který bude mít jedinečné ID a dle něhož se potom bude mazat. Navíc si můžu vytvořit ještě popisek k řádku formuláře a oddělit celý řádek tagem BR. Takže si všechny tyto elementy vytvořím:
1 2 3 4 |
var text = document.createTextNode('Možnost: '); var p = document.createElement('span'); p.setAttribute('id', 'span_' + num_of_lines ); var br = document.createElement('br'); |
Nyní stačí pouze ve správném pořadí volat appendChild a všechny elementy do sebe zanořit:
1 2 3 4 5 6 7 8 9 10 11 |
select.appendChild(option1); select.appendChild(option2); select.appendChild(option3); select.appendChild(option4); p.appendChild(text); p.appendChild(input); p.appendChild(select); p.appendChild(br); x.appendChild(p); |
Nakonec upravím proměnnou num_of_lines přičtením 1.
Funkce function minus(element){}
Tato funkce je oproti přidávání mnohem jednodušší. Stačí si pouze předat element a z tohoto elementu vymazat příslušný span, jak jsme si jej při přidávání vytvořili:
1 2 3 |
var d = document.getElementById( element ); var olddiv = document.getElementById( 'span_' + num_of_lines ); d.removeChild(olddiv); |
Celý kód si můžete prohlídnout zde:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
<script type="text/javascript"> var num_of_lines = 0; function plus(element){ num_of_lines ++; var x = document.getElementById( element ); var input = document.createElement('input'); input.setAttribute('name', 'input[]' ); var option1 = document.createElement('OPTION'); option1.setAttribute('value', 'prvni'); var option2 = document.createElement('OPTION'); option2.setAttribute('value', 'druha'); var option3 = document.createElement('OPTION'); option3.setAttribute('value', 'treti'); var option4 = document.createElement('OPTION'); option4.setAttribute('value', 'ctvrta'); var txt1 = document.createTextNode("Krátký text"); option1.appendChild(txt1); var txt2 = document.createTextNode("Dlouhý text"); option2.appendChild(txt2); var txt3 = document.createTextNode("Celé číslo"); option3.appendChild(txt3); var txt4 = document.createTextNode("Desetinné číslo"); option4.appendChild(txt4); var select = document.createElement('select'); select.setAttribute('name', 'select[]' ); var text = document.createTextNode('Možnost: '); var p = document.createElement('span'); p.setAttribute('id', 'span_' + num_of_lines ); var br = document.createElement('br'); select.appendChild(option1); select.appendChild(option2); select.appendChild(option3); select.appendChild(option4); p.appendChild(text); p.appendChild(input); p.appendChild(select); p.appendChild(br); x.appendChild(p); } function minus(element){ if( num_of_lines < 1 ) return; var d = document.getElementById( element ); var olddiv = document.getElementById( 'span_' + num_of_lines ); num_of_lines--; d.removeChild(olddiv); } </script> <a href="#" onclick="plus('new_sab'); return false;" >+</a> / <a href="#" onclick="minus('new_sab'); return false;" >-</a><br /> <a href="#" onclick="for( i = 0; i < 3; i++ ) plus('new_sab'); return false;">+ 3</a> / <a href="#" onclick="for( i = 0; i < 3; i++ ) minus('new_sab'); return false;">- 3</a> / <form method="post" id="new_sab"> <div> </div> </form> |
Užitečná funkce, ale specifikace XForms(http://www.w3.org/MarkUp/For ms/2003/xforms-for-html-authors.htm l)
to řeší elegantněji. Škoda, že má prozatím nulovou porporu prohlížečů.
Hezky popsane, nicmene mam problem s tim ze IE6 mi hlasi problem u
x.appendChild(p)
"null" is null or not an object
PS:primo u tebe na strankach radka 153, znak 1.
Sice vse funguje tak jak ma, ale .. 🙂
netusis co je spatne ?
Děkuji, to je přesně ono:-)
Chtěl bych moc poděkovat za tento script. V JavaScriptu prakticky nedělám, jsem hlavně přes PHP a CSS – to jsou moje domény a přišlo mi hloupé, abych kvůli každému řádku musel refreshovat stránku, aby tam pen řádek byl od serveru poslán. Přeci jenom bych se rád zeptal, jak mám syntakticky napsat ten odkaz, aby u člověka který nemá zapnutý javascript fungoval jako normální odkaz, ale u člověka, který ho zapnutý má, se provedl jenom ten script? Chtěl bych si to takhle pojistit – kdyby někdo neměl zapnutý JavaScript, tak bych mu nový řádek poslal přes PHP…