Podpora HTML5 ve formulářích

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8111
+
0
-

HTML5 přichází s celou řadu novinek pro webové formuláře. Už dnes je lze používat v Nette. Ačkoliv podpora v prohlížečích je stále slabá, příliš to nevadí. HTML5 zavádí například nové typy elementů <INPUT> jako email, number, url, range, datetime a pokud je prohlížeč nezná, použije výchozí text a vše bude fungovat postaru. Zná-li je, nabídne uživateli lepší komfort. Nic tedy nebrání tyto typy už dnes používat.

Vytvořit prvek s HTML5 typem email lze tímto způsobem:

$form->addText('email-address', 'Vás e-mail:')
	->setType('email') // vytvoří <input type=email>

nebo (lépe?) rovnou v šabloně:

<td>{$form['email']->control->type('email')->cols(35)}</td>

Prohlížeč pak sám validuje platnost emailové adresy, u mobilních zařízení nabídne klávesnici, která je pro zadávání emailů vhodnější atd.

Obdobně můžeme nastavit atributy jako placeholder, autofocus, autocomplete atd:

$form->addText('query', 'Search:')
	->setType('search')
	->setAttribute('placeholder', 'Search the website')
	->setAttribute('autofocus');

 // vytvoří <input type=search placeholder="Search the website" autofocus>

Nette podporuje HTML5 aktivně, například při vytvoření táhla nastaví hodnoty min a max:

$form->addText('precision', 'Precision:')
	->setType('range')
	->addRule(Form::RANGE, 'Precision must be in range from %d to %d', array(0, 100));

// <input type="range" max="100" min="0" name="precision" />

Bohužel, nativní validace na straně prohlížeče je obvykle nedostatečná, nezobrazují se chybové zprávy a špatně se kombinuje s uživatelskou validací pomocí JavaScriptu. Z toho důvodu podpora hlouběji nesahá a například povinné prvky nezískávají atribut required. Také typ email nelze kombinovat s „empty value“ apod.

HTML5 je tedy vhodné využívat doplňkově. Chcete-li vytvořit políčko pro zadání čísla number, nezapomeňte uvést i klasická validační pravidla:

$form->addText('count', 'Number:')
	->setType('number') // <input type=number>
	->setDefaultValue(10)
	->addRule(Form::INTEGER, 'Must be numeric value')
	->addRule(Form::RANGE, 'Must be in range from %d to %d', array(1, 100)); // opět doplní min a max
Patrik Votoček
Člen | 2221
+
0
-

A nešlo by aby ->setType('email') rovnou udělal ->addRule(Form::EMAIL) ?

jtousek
Člen | 951
+
0
-

vrtak-cz napsal(a):

A nešlo by aby ->setType('email') rovnou udělal ->addRule(Form::EMAIL) ?

Souhlasím. Zvolil bych totéž chování i pro RANGE, NUMBER a INTEGER.
Přičemž pokud element má Rule jak RANGE tak INTEGER / NUMBER, RANGE má větší přednost.

Je ovšem nutné dát pozor na podmíněná pravidla:

<?php
// tohle by type="range" vyvolat nemělo!
$form->addText('precision', 'Precision:')
        ->addConditionOn($form['select'], Form::EQUAL, 1)
            ->addRule(Form::RANGE, 'Precision must be in range from %d to %d', array(0, 100));

// ...ale tohle ano!
$form->addText('precision', 'Precision:')
        ->addCondition(Form::FILLED)
            ->addRule(Form::RANGE, 'Precision must be in range from %d to %d', array(0, 100));
?>

Mimochodem jsem teď koukal do zdrojáku, jaký je rozdíl mezi Form::INTEGER a Form::NUMERIC se zjištěním, že vůbec žádný. Abych pravdu řekl tak NUMERIC ve mě názvem vyvolával dojem, že výsledkem musí být řetězec ze samých číslic, ale třeba „-5“ by projít nemělo (což teď projde).

Nebo jsem jediný komu v Nette chybí validátor na kladná celá čísla? :D

Editoval jtousek (10. 8. 2010 7:44)

Patrik Votoček
Člen | 2221
+
+1
-

jtousek napsal(a):

Nebo jsem jediný komu v Nette chybí validátor na kladná celá čísla? :D

->addRule(Form::RANGE, 'Number must be positive', array(0, NULL))

Ondřej Mirtes
Člen | 1536
+
0
-

+1 :D

Jsem proti, aby addRule(Form::EMAIL) automaticky nastavilo <input type="email"> (pro některé kombinace pravidel by se těžko definovalo, jaký type má mít ten formulářový prvek), ale obráceně (při setType('email')) bych validaci na tvar e-mailu určitě nastavil, tam to smysl dává.

jtousek
Člen | 951
+
0
-

vrtak-cz napsal(a):

->addRule(Form::RANGE, 'Number must be positive', array(0, NULL))

Oh, díky. :) Přiznám se, že tohle mě nenapadlo, nevěděl jsem, že NULL funguje pro RANGE takhle.

Ještě dotaz, když nastavím RANGE, měl bych ještě nastavit INTEGER / NUMERIC nebo to postrádá jakýkoli smysl?

Ondřej Mirtes napsal(a):

+1 :D

Jsem proti, aby addRule(Form::EMAIL) automaticky nastavilo <input type="email"> (pro některé kombinace pravidel by se těžko definovalo, jaký type má mít ten formulářový prvek), ale obráceně (při setType('email')) bych validaci na tvar e-mailu určitě nastavil, tam to smysl dává.

S tím mám trochu problém – ztrácíš možnost definovat chybovou hlášku ⇒ použije se výchozí.

Co nastavit typ pouze v případě, kdy to pravidlo není obalené vůbec žádnou podmínkou?

Petr Motejlek
Člen | 293
+
0
-

Já bych automaticky nenastavoval vůbec nic, dokud nebudou ty nové formuláře nějakou dobu venku a každý si to ošahá bez toho. Pak se o automatickém nastavování můžeme bavit. Kvůli automatice, která tady od stolu může vypadat naprosto super, si taky můžeme za tejden rvát vlasy…

Nebylo by vhodnější namísto addRule, které nastavují pouze datový typ, předělat ty metody, co formuláře používají pro přidávání jednotlivých elementů? Teď to vypadá, že by to taky mohlo skončit tím, že kvůli výběru data budu muset zavolat Form::addText(‚date‘, „Date“)->addRule(Form::DATE, „Not a date!“), takže vlastně přidávám text, ale omezuju si ho na datum – to zní ošklivě ;). Radši bych dělal Form::addDate(‚date‘, „Date“, „Not a date!“). Na ostatní věci, jako RANGE, FILLED, atd. by addRule mohl zůstat, ale omezení na datový typ bych vytáhnul.

Editoval Petr Motejlek (11. 8. 2010 9:45)

redhead
Člen | 1313
+
0
-

@Petr Motejlek: +1

Honza Kuchař
Člen | 1662
+
0
-

Petr Motejlek: Souhlasím všemi deseti. Něco podobného tu mám udělaného.

Lopo
Člen | 277
+
0
-

ja osobne bych napr. uvital aby form mal svoje ID, tj aby som mohol pouzivat $form->getHtmlId() tak ako to ide u jednotlivych kontrolov vo formoch

co sa tyka datovych typov prvkov, tak @Petr Motejlek: +1

predsa len addRule() ma pridat pravidlo a nie nastavovat datovy typ

Patrik Votoček
Člen | 2221
+
0
-

Form kdysi své ID míval… Ale už nemá, aby bylo možné na jedné stránce použít vícekrát jeden Form.

ic
Člen | 430
+
0
-

Změnilo se tam něco s FILLED ? protože obyčejná validace emailu (serverová část):

$form->addText('email', $translator->translate('Email'), 40, 250)
	->addCondition(Form::FILLED)
	->addRule(Form::EMAIL, 'E-mail is not valid');

mi klidně nechá projít prázdný řetězec jakoby nic. Dělá se teď validace vyplnění nějak jinak nebo je to bug?

*Testováno na nejnovější ‚Nightly Build‘ verzi ze včerejška tedy 7b95cd3 *

paranoiq
Člen | 392
+
0
-

->addRule(Form::FILLED) !!!

ic
Člen | 430
+
0
-

paranoiq napsal(a):

->addRule(Form::FILLED) !!!

díky

westrem
Člen | 398
+
0
-

Lopo napsal(a):

ja osobne bych napr. uvital aby form mal svoje ID, tj aby som mohol pouzivat $form->getHtmlId() tak ako to ide u jednotlivych kontrolov vo formoch

co sa tyka datovych typov prvkov, tak @Petr Motejlek: +1

predsa len addRule() ma pridat pravidlo a nie nastavovat datovy typ

+1

David Grudl
Nette Core | 8111
+
0
-

Form své ID má, dá se měnit přes $form->elementPrototype->id = .... Metodu setHtmlId() mají jen prvky formuláře, protože u nich přístup přes controlPrototype->id použít nelze.