Pokud máme vytvořit dlouhý formulář, je možné ho rozdělit na několik stránek, abychom uživatele nevylekali a neodradili je od vyplňování. Několikastránkový formulář je však nutno správně zkonstruovat a ošetřit, abychom nezpůsobili sobě i jeho uživatelům více problémů, než je nezbytně nutné.

Řešení v PHP

Pokud se vyplněné hodnoty jednotlivých stránek rozhodneme přenášet na server, musíme pro ně zvolit vhodné úložiště. Vhodným místem jsou skrytá formulářová pole, protože jsou přímo svázána s vyplňovaným formulářem, jejich nevýhodou ale je, že se data neustále přenášejí tam a zpátky. Vyplněné hodnoty je možné ukládat také rovnou do databáze (do záznamu označeného ve zvláštním sloupci jako neúplný).

Nevhodným místem pro uložení jsou běžné session proměnné, protože znemožňují vyplňování více formulářů najednou. Při zkombinování session proměnných se skrytým formulářovým polem je ale použít můžeme – stačí, když vyplněná data budeme ukládat do prvku pole a identifikátor tohoto prvku si budeme přenášet ve skrytém formulářovém poli.

<?php
$posledni_stranka = 1;
if (!$_POST) {
   $stranka = 0;
   $registrace = array();
} else {
   $stranka = intval($_POST[„stranka“]);
   $form_id = (isset($_POST[„form_id“]) ? intval($_POST[„form_id“]) : count($_SESSION[„registrace“]));
   $registrace = &$_SESSION[„registrace“][$form_id];
   $chyba = „“;
   
   // uložení vyplněných hodnot
   foreach ($_POST as $key => $val) {
      if ($key != „form_id“ && $key != „zpet“ && $key != „stranka“) {
         $registrace[$key] = stripslashes($val);
      }
   }
   
   if ($_POST[„zpet“]) {
      $stranka–;
   } else {
      
      // kontrola vyplněných hodnot
      switch ($stranka) {
         case 0:
            if (!strlen($_POST[„jmeno“])) {
               $chyba .= „Jméno nesmí být prázdné.\n“;
            }
         break;
         case 1:
            if (!check_email($_POST[„email“])) {
               $chyba .= „Vyplňte prosím e-mail.\n“;
            }
            if (!$chyba && !mysql_query(„INSERT INTO uzivatele (jmeno, email) VALUES (‚“ . addslashes($registrace[„jmeno“]) . „‚, ‚“ . addslashes($registrace[„email“]) . „‚)“)) {
               $chyba = „Data se nepodařilo uložit.“;
            }
            if (!$chyba) {
               header(„Location: ok.php“);
               exit;
            }
         break;
      }
      if (!$chyba) {
         $stranka++;
      }
   }
}
// vypsání formuláře
echo „<form action=“ method=’post‘>\n“;
if ($_POST) {
   echo „<input type=’hidden‘ name=’form_id‘ value=’$form_id‘ />\n“;
   echo „<input type=’hidden‘ name=’stranka‘ value=’$stranka‘ />\n“;
   if ($chyba) {
      echo „<p>$chyba</p>\n“;
   }
}
switch ($stranka) {
   case 0:
      echo ‚Jméno: <input name=“jmeno“ value=“‚ . htmlspecialchars($registrace[„jmeno“]) . ‚“ />‘;
   break;
   case 1:
      echo ‚E-mail: <input name=“email“ value=“‚ . htmlspecialchars($registrace[„email“]) . ‚“ />‘;
   break;
}
echo „\n<input type=’submit‘ value='“ . ($stranka < $posledni_stranka ? „Další“ : „Dokončit“) . „‚ />\n“;
if ($stranka) {
   echo „\n<input type=’submit‘ name=’zpet‘ value=’Zpět‘ />\n“;
}
echo „Strana: “ . ($stranka + 1) . „/“ . ($posledni_stranka + 1) . „\n“;
echo „</form>\n“;
?>

Viz též článek Kontrola e-mailové adresy.

V části vypsání formuláře se vypíše aktuální stránka formuláře a tlačítka pro pohyb po stránkách formuláře. Tlačítko Další je před tlačítkem Zpět proto, aby bylo výchozí – jejich vizuální pořadí lze prohodit stylem.

Pokud uživatel formulář odešle, data se uloží do prvku pole v session proměnné. Pokud se uživatel nechtěl vrátit na předchozí stránku, vyplněné hodnoty se zkontrolují a pokud jsou v pořádku, přejde se na další stránku. Na poslední stránce se provede přesměrování na skript informující o úspěšném vyplnění a uložení hodnot formuláře.

Řešení v JavaScriptu

Než začneme vytvářet vícestránkový formulář, měli bychom si uvědomit, jakou pro to vlastně máme motivaci. Je formulář moc dlouhý a my nechceme uživatele odradit od jeho vyplňování? Nebo se podoba dalších kroků liší podle toho, co uživatel vyplnil dříve? Nebo chceme, aby se první stránka formuláře rychle stáhla?

V prvním a, s vyvinutím určitého úsilí, i v druhém případě můžeme stránkování vytvořit na straně klienta v JavaScriptu. Tím zároveň zrychlíme odezvy při přechodu mezi stránkami formuláře, což je dobrou protiváhou ke třetímu případu. Zpracování na serveru bude stejné jako u obyčejného formuláře, uživatelům s vypnutým JavaScriptem jednoduše zobrazíme všechny stránky formuláře najednou.

<form action=““ method=“post“>
<div id=“stranka-0″>
Jméno: <input name=“jmeno“ value=“<?php echo htmlspecialchars(stripslashes($_POST[„jmeno“])); ?>“ />
</div>
<div id=“stranka-1″>
E-mail: <input name=“email“ value=“<?php echo htmlspecialchars(stripslashes($_POST[„email“])); ?>“ />
</div>
<script type=“text/javascript“>
var stranka = 0;
var posledni_stranka = 1;
function stranka_prechod(f, posun) {
   var chyba = “;
   if (posun > 0) {
      switch (stranka) {
         case 0:
            if (!f[‚jmeno‘].value) {
               chyba += ‚Jméno nesmí být prázdné.\n‘;
            }
         break;
         case 1:
            if (!check_email(f[‚email‘].value)) {
               chyba += ‚Vyplňte prosím e-mail.\n‘;
            }
         break;
      }
      if (chyba) {
         alert(chyba);
      } else if (stranka == posledni_stranka) {
         return true;
      }
   }
   if (!chyba) {
      document.getElementById(‚stranka-‚ + stranka).style.display = ‚none‘;
      stranka += posun;
      document.getElementById(‚stranka-‚ + stranka).style.display = “;
      document.getElementById(‚zpet‘).disabled = !stranka;
      document.getElementById(‚dalsi‘).value = (stranka == posledni_stranka ? ‚Dokončit‘ : ‚Další‘);
      document.getElementById(‚stranka-cislo‘).innerHTML = stranka + 1;
   }
   return false;
}
for (var i=1; i <= posledni_stranka; i++) {
   document.getElementById(‚stranka-‚ + i).style.display = ‚none‘;
}
document.write(‚<input type=“button“ id=“zpet“ value=“Zpět“ onclick=“stranka_prechod(this.form, -1);“ disabled=“disabled“ />\n‘);
document.write(‚<input type=“submit“ id=“dalsi“ value=“Další“ onclick=“return stranka_prechod(this.form, 1);“ />\n‘);
document.write(‚Strana: <span id=“stranka-cislo“>1</span>/‘ + (posledni_stranka + 1) + ‚\n‘);
</script>
<noscript><p><input type=“submit“ value=“Dokončit“ /></p></noscript>
</form>

Tlačítka pro přechod mezi stránkami formuláře budeme zobrazovat vždy obě – u tlačítka Zpět budeme nastavovat jeho „zakázanost“, u tlačítka Další zase jeho popis. Funkce stranka_prechod zkontroluje při přechodu na další stránku formuláře vyplněné hodnoty a na poslední stránce dovolí formulář odeslat. V jiném případě skryje starou stránku formuláře a zobrazí novou. Kontrolu hodnot v JavaScriptu musíme brát samozřejmě jen jako službu pro uživatele a na serveru si musíme kvůli bezpečnosti a konzistenci data zkontrolovat znovu.

Souhrn

Jako uživateli mi vícestránkové formuláře moc příjemné nejsou, ale když už k nim provozovatel webu sáhne, měly by být vytvořeny s ohledem na pohodlí uživatele. Především by mělo fungovat vyplňování více formulářů najednou a pokud to je možné, přechody mezi stránkami by měly být co nejrychlejší. Tyto požadavky oba zde popsané způsoby splňují.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět