Formulár vykreslený pomocou FormMacros pri metode GET nezohľadňuje query v action
- dakota
- Člen | 148
Nette Framework 2.0-dev z 2011–06–24
Formulár vykreslený pomocou FormMacros {form name}...{/form}
v prípade metódy GET nezohľadňuje query v action.
Napr. v prípade
$form->setAction('index.php?key=value');
je formulár odoslaný iba na index.php
bez
key=value
.
DefaultFormRenderer pri metóde GET query v action vykresľuje pomocou HiddenField, vo FormMacros táto časť nie je.
Návrh na úpravu FormMacros (doplnené z DefaultFormRenderer::renderBegin())
public static function install(Latte\Parser$parser)
{
...
$me->addMacro('form', array($me, 'macroForm'), ...);
}
public function macroForm(MacroNode $node, $writer)
{
return $writer->write('$form = $control[%node.word]; echo Nette\Latte\Macros\FormMacros::beginForm($form, %node.array)');
}
public static function beginForm($form, $attributes)
{
if (strcasecmp($form->getMethod(), 'get') === 0) {
$el = clone $form->getElementPrototype();
$url = explode('?', (string) $el->action, 2);
$el->action = $url[0];
$s = '';
if (isset($url[1])) {
foreach (preg_split('#[;&]#', $url[1]) as $param) {
$parts = explode('=', $param, 2);
$name = urldecode($parts[0]);
if (!isset($form[$name])) {
$s .= Nette\Utils\Html::el('input', array('type' => 'hidden', 'name' => $name, 'value' => urldecode($parts[1])));
}
}
$s = "\n\t" . Nette\Utils\Html::el('div')->setHtml($s);
}
return $el->addAttributes($attributes)->startTag() . $s;
} else {
return $form->getElementPrototype()->addAttributes($attributes)->startTag();
}
}
Editoval dakota (25. 6. 2011 12:48)
- medvedobijec
- Člen | 11
Ahoj, narazil jsem dnes na podobný problém s odesíláním GETového
formuláře a příčina je stejná. U renderování formuláře s metodou GET
osekne DefaultFormRenderer action a doplní hidden políčko – např
<input type="hidden" name="do" value="myForm-submit" />
Jenomže to se v případě FormMacros neděje.
- Mikulas Dite
- Člen | 756
FormMacros nechtějí mít
závislost na DefaultFormRenderer
. Takhle chyba se bude ale ve stringu
opravovat špatně. Přesouvat to do další funkce není vůbec nette-way.
Co kdyby to závislost mělo, ale nějakým setterem se dal
DefaultFormRenderer
nahradit za potomka? To by byl win-win,
protože se form-macros zjednodušší a navíc se bude moc chování formů
měnit jednou snadno přenositelnou třídou.
- dakota
- Člen | 148
Závislosť FormMacros na nejakom rendereri by možno malo výhodu aj pri opakujúcich sa veciach ako sú napr.:
- pri povinných prvkoch doplnenie
*
, triedy class=„required“ a pod - doplnenie dvojbodky
{label title}Titulok:<span class="required-suffix" n:if="$form['title']->isRequired()">*</span>{/label}
by stačilo zapisať ako
{label title}Titulok{/label}
Správanie by sa dalo upraviť nastavením rendereru, príp. jeho nahradením.
DefaultFormRenderer je nato však dosť obsiahly. Možno by stačil nejaký zjednodušený renderer.
Editoval dakota (25. 6. 2011 20:59)
- medvedobijec
- Člen | 11
Tak jsem si jako workaround zkopíroval kód z
DefaultFormRenderer
u a upravil makro následovně. Ale je to
šílenost a chtělo by to asi řešit nějak koncepčně.
$me->addMacro('form', '
$form = $control[%node.word];
if (strcasecmp($form->getMethod(), \'get\') === 0) {
$el = clone $form->getElementPrototype();
$url = explode(\'?\', (string) $el->action, 2);
$el->action = $url[0];
$s = "";
if (isset($url[1])) {
foreach (preg_split(\'#[;&]#\', $url[1]) as $param) {
$parts = explode(\'=\', $param, 2);
$name = urldecode($parts[0]);
if (!isset($form[$name])) {
$s .= Nette\Utils\Html::el(\'input\', array(\'type\' => \'hidden\', \'name\' => $name, \'value\' => urldecode($parts[1])));
}
}
$s = "\n\t" . Nette\Utils\Html::el(\'div\')->setHtml($s);
}
echo $el->startTag() . $s;
} else {
echo $form->getElementPrototype()->addAttributes(%node.array)->startTag();
}',
'?><div><?php
foreach ($form->getComponents(TRUE, \'Nette\Forms\Controls\HiddenField\') as $_tmp) echo $_tmp->getControl();
if (iterator_count($form->getComponents(TRUE, \'Nette\Forms\Controls\TextInput\')) < 2) echo "<!--[if IE]><input type=IEbug disabled style=\"display:none\"><![endif]-->";
?></div>
<?php echo $form->getElementPrototype()->endTag()');