Dynamicky generovaný formulář – vzdálenosti – dělám to správně
- motorcb
- Člen | 552
Zdravim.
Pokouším se o jednoduchý dynamicky generovaný formulář pro zadávání
vzdálenosti mezi městy (matice a * a). Měst bude dynamický počet.
Dělám to takto: definice zdrojových dat. Matice měst a vzdáleností:
$this->array = array();
$this->array["Praha"]["Praha"] = "X";
$this->array["Praha"]["Bratislava"] = 330;
$this->array["Praha"]["Rim"] = 1320;
$this->array["Bratislava"]["Praha"] = 330;
$this->array["Bratislava"]["Bratislava"] = "X";
$this->array["Bratislava"]["Rim"] = 100;
$this->array["Rim"]["Praha"] = 1320;
$this->array["Rim"]["Bratislava"] = 100;
$this->array["Rim"]["Rim"] = "X";
$this->template->array = $this->array;//odeslu do sablony
Vytvoření komponent pro formulář:
protected function createComponentPriceForm()
{
$form = new Form;
foreach ( $this->array as $rowNameFrom => $row )
{
foreach ( $row as $rowNameTo => $rowCelText )
{
$form->addText( "distance_" . $rowNameFrom . "_" . $rowNameTo, 'Vzdalenost' )
->setValue( $rowCelText );
}
}
$form->addSubmit( 'send', 'Upravit ceník' );
$form->onSuccess[] = $this->priceFormSucceeded;
return $form;
}
public function priceFormSucceeded( $form )
{
$values = $form->getValues();
dump( $values );
}
Kde skládám název textboxu: distance_odkud_kam
Šablona:
{form priceForm}
<table>
<tr>
<th>Město</th>
{foreach $array as $key => $header}
<th>{$key}</th>
{/foreach}
</tr>
{foreach $array as $rowNameFrom => $row}
<tr>
<th>{$rowNameFrom}</th>
{foreach $row as $rowNameTo => $rowCelText}
<td>
{*{$rowNameFrom}-{$rowNameTo} = {$rowCelText}<br/>*}
{input distance_{$rowNameFrom}_{$rowNameTo}}
</td>
{/foreach}
</tr>
{/foreach}
</table>
{input send}
{/form priceForm}
Po odeslání formuláře bych rozparsroval jednotlivé textboxy ze kterých zjistím město odkud, kam a novou vzdálenost.
Je mé řešení korektní, nebo existuje elegantnější způsob?
Díky
- s4muel
- Člen | 92
ja by som skusil asi nejako takto:
public function createComponentPriceForm() {
$cities = array(
'ba' => 'bratislava',
'bb' => 'banska bystrica',
'ke' => 'kosice',
//...
);
//+ matica vzdialenosti, napr:
$distance['ba']['bb'] = 10;
$distance['bb']['ke'] = 20;
//...
$form = new Nette\Application\UI\Form;
//mesta v riadkoch
foreach($cities as $city_from_short => $city_from_full) {
//vytvorenie nazvu premennej pre pod-formular (moze byt cokolvek, len unikatne. bude pouzite nizsie_
$subform_variable_name = 'sf_' . $city_from_short;
//vytvorenie noveho pod-formulara (containera)
$$subform_variable_name = $form->addContainer($city_from_short);
//mesta v stlpcoch
foreach($cities as $city_to_short => $city_to_full) {
//ak je mesto rozdielne, tak pridaj normalny povoleny input do sub-formulara
if($city_to_short != $city_from_short) {
$$subform_variable_name->addText($city_to_short, $city_to_full);
//+ nastavenie default hodnoty podla potreby
}
//inak (ak je mesto v riadku a stlpci rovnake) disabluj input
else {
$$subform_variable_name->addText($city_to_short, $city_to_full)->setDisabled();
}
}
}
$form->addSubmit('submit');
$form->onSuccess[] = $this->priceFormSubmitted;
return $form;
}
potom budes mat vysledky nasledovne a nemusis ich parsovat:
Nette\ArrayHash #375e
ba => Nette\ArrayHash #eca9
bb => "50" (2)
ke => "100" (3)
bb => Nette\ArrayHash #8113
ba => "50" (2)
ke => "50" (2)
ke => Nette\ArrayHash #1fa5
ba => "100" (3)
bb => "50" (2)
Editoval s4muel (18. 1. 2014 23:23)
- s4muel
- Člen | 92
no neviem, ci najidealnejsie, ale skus takto:
treba dostat do template pole s mestami: v createComponentPriceForm() factory
by malo stacit
$this->template->cities = $cities;
a potom v latte:
{form priceForm}
<table>
<tr>
<th>mesto</th>
{*vypiseme nazvy miest do hlavicky tabulky*}
<th n:foreach="$cities as $city_full">{$city_full}</th>
</tr>
{*neviem, ako inak ziskat vsetky sub-formulare, tak iterujem cez vsetky formularove komponenty,
mozno poradi niekto nieco lepsie*}
{foreach $form->components as $component}
{*pokracujem len ak je component triedy form\container (sub-formular) a ked sa jeho nazov nachadza v poli s mestami (a teda nie je to nejaky iny sub-formular)*}
{if $component instanceof \Nette\Forms\Container && array_key_exists($component->name, $cities)}
<tr>
{*$component->name je napr 'ba' a preto do prveho stlpca vypiseme $cities['ba'] atd...*}
<th>{$cities[$component->name]}</th>
{*iterujeme cez controls sub-formulara tohto cyklu a vypiseme jeho podradene componenty/mesta *}
<td n:foreach="$component->controls as $item">{$item->control}</td>
</tr>
{/if}
{/foreach}
</table>
{input submit}
{/form priceForm}