Duplikování položek formuláře v JS

V případě, že ve webové aplikaci potřebujeme umožnit zadat více položek stejného typu, hodí se k tomu možnost JavaScriptem jednotlivá políčka duplikovat.

Alternativou je zobrazit předpokládaný počet políček rovnou a při zpracování formuláře brát v úvahu jen ta vyplněná. Dynamická změna počtu položek vypadá ale jako lepší volba.

Samostatná živá ukázka

Metoda cloneNode

Základem je JS metoda cloneNode, která naklonuje první položku, a metoda appendChild, která ji později vloží.

var prvniPolozka = document.getElementById('sablona');
var sablona = prvniPolozka.cloneNode(true);

Pro snadné klonování více <input>ů či jiných formulářových prvků v rámci jedné položky je ideální všechno obalit nějakým elementem – nejspíš <div>em.

<div class="polozka" id="sablona">
  <input name="policko1[]">
  <input name="policko2[]">
</div>

Za pozornost dále stojí, že klonování proběhne nadvakrát:

  • Ihned po načtení stránky se naklonuje první položka.
  • Při kliknutí na tlačítko Přidat se naklonuje tato kopie.

Proč? Kdyby se klonovala přímo živá první položka, promítl by se do klonu její stav (vyplněné hodnoty a podobně), což většinou není žádoucí. Další výhoda je v tom, že nemusíme řešit stav, kdy uživatel odstraní úplně všechny položky. I po odstranění všeho půjde přidat položku novou.

Pokud bychom chtěli zabránit odebrání i první položky, můžeme odebírací tlačítko skrýt pomocí CSS (display: none) s využitím CSS selektoru :first-child (IE 7+).

.polozka:first-child .odebrat {
  display: none;
}

Odebrání removeChild

Odebrání bude velmi snadné. Tlačítko Odebrat bude v každém <div>u s položkami. V případě, že tlačítko bude přímo v tomto obalu, stačí si najít jeho rodiče (parentNode) a provést removeChild.

function odebrat(el) {
  var polozka = el.parentNode;
  polozka.parentNode.removeChild(polozka);
}

Funkci odebrat se pro zjištění rodiče předá odebírací tlačítko prostřednictvím this.

<button onclick="odebrat(this)">
  × Odebrat
</button>

Udělení focusu

Po kliknutí na Přidat je vhodné rovnou označit první políčko přidané položky, aby do něj šlo rovnou psát:

kopie.getElementsByTagName("input")[0].focus();

Možná vylepšení

V závislosti na konkrétním použití je k úvaze případné vylepšení:

  • Novou položku přidávat místo na konec za položkou naposledy upravenou.

    K tomu poslouží metoda insertBefore v kombinaci s nextSibling.

    polozky.insertBefore(kopie, aktualniPolozka.nextSibling);
  • Novou položku přidávat automaticky, když je předchozí (částečně) vyplněná. Tedy mít stále o jednu více položek, než je potřeba.

  • Někdy se může hodit možnost Vytvořit na základě předchozí, kde se naopak bude kopírovat obsah předchozí položky včetně vyplněných hodnot.

  • Pohrát si s tabindexem, aby po vyplnění posledního políčka položky klávesa Tab aktivovala tlačítko Přidat namísto Odebrat.

    Špatné pořadí políček je častou chybou formulářů.

    Upravená ukázka

  • Tlačítko Přidat umístit na místo, kde se nebude pohybovat v závislosti na počtu položek. Případně ho přidat ihned za položku před tlačítko Odebrat.

Zpracování na serveru

Pro pohodlné zpracování na serveru je ideální dávat prvkům formuláře názvy s hranatými závorkami [], aby se s nimi dalo snadno pracovat jako s polem.

To je všechno. Líbil se vám článek a chcete se dozvědět, až vyjde další?

Sledujte:

 

Připomínky mi pište do komentářů ↓

Zapamatování formulářových polí

Automatické zapamatování formulářů

Při vyplňování delších formulářů se je hodí obsah průběžně ukládat. Jak na to?

AJAX upload souborů

Upload souborů bez obnovení stránky

Jak vytvořit ajaxové nahrávání souborů na server bez obnovení stránky.

Plynulý přesun focusu

Plynulý přesun focusu

Plynulé přesouvání focusu mezi jednotlivými položkami formuláře.

Zvyšování hodnoty inputů

Zvyšování hodnoty inputů

Jak zpříjemnit zadávání číselných hodnot nebo času do <input>ů tlačítky plus a mínus.

Textarea s automatickou výškou

Automatická výška <textarea>

Jak zajistit, aby se výška textového pole přizpůsobovala délce textu.

Komentáře