Může CheckboxList vracet associativní pole místo indexového?
- FilipDolezal
- Člen | 9
Dobrý den, snažím se přepsat chování checkboxlistu tak, aby místo indexového pole vracelo asociativní.
Například CheckboxList, který je vytvořen takto:
$arr = [
"po" => "Pondělí",
"ut" => "Úterý",
...
]
$form->addCheckboxList("dny", "Vyber dny", $arr)
Po zaškrtnutí např.: po
, st
, a
ct
vrátí indexové pole vybraných polí:
array (3)
0 => 'po'
1 => 'st'
2 => 'ct'
Jak docílit, aby mi po odeslání formuláře přišlo associativní pole?
array (7)
po => true
ut => false
st => true
ct => true
pa => false
...
Děkuji
- Bulldog
- Člen | 110
@Pepino Zbytečně složité. Tvoje složitost je
O(n2) Daleko lepší řešení je toto:
nadefinování pole, které bude pro výběr v checkBoxListu: (původní
autorovo)
$arr = [
"po" => "Pondělí",
"ut" => "Úterý",
...
]
$form->addCheckboxList("dny", "Vyber dny", $arr);
Příprava návratové hodnoty
$resultArr = array_map(fn($item) => false, $arr); // array_map => kdo ví, jestli s původním nebude chtít ještě něco dělat.
Doplnění návratové hodnoty o vybraná pole
foreach ($values->dny as $den) {
$resultArr[$den] = true;
}
Sice se o trochu více napíšeš, ale vzhledem k tomu, že to napíšeš jednou a pak už jen používáš komponentu(input), tak o 3 řádky navíc ti neublíží a vykoupí tě složitostí O(n)
@netteman To na to, co chce tazatel snad nemá vůbec vliv ne? Mu stačí jen ty hodnoty, které jsou zaškrtnuté. Výsledné pole si z nich pak dokáže sestavit viz výše.
Editoval Bulldog (11. 5. 2022 17:07)
- FilipDolezal
- Člen | 9
@Bulldog toto řešení mi dává největší smysl. Doufal jsem, že se mi podaří přepsat chování checkboxlistu a ne zpracování vrácené hodnoty, ale vaše řešení není vůbec dlouhé ani složité. Děkuji
Editoval FilipDolezal (11. 5. 2022 17:18)
- Bulldog
- Člen | 110
@FilipDolezal Upravit výchozí chování samozřejmě můžeš… :) Třeba takto:
class CheckboxListAssoc extends Nette\Forms\Controls\CheckboxList
{
private array $items;
public function __construct($label = null, array $items = null)
{
parent::__construct($label, $items);
$this->items = $items ?? [];
}
public function getValue(): array
{
$selectedDays = parent::getValue();
$items = array_map(fn($item) => false, $this->items);
foreach ($selectedDays as $selectedDay) {
$items[$selectedDay] = true;
}
return $items;
}
}
class Form extends Nette\Application\UI\Form
{
public function addCheckboxListAssoc(string $name, string $label = null, array $items = null): CheckboxListAssoc
{
return $this[$name] = new CheckboxListAssoc($label, $items);
}
}
a v aplikaci pak už budeš místo Nette\Application\UI\Form
používat tento tvůj Form
.
Takže reálně když si to zkusíš takto:
public function createComponentForm(): Form
{
$form = new Form();
$arr = [
'po' => 'Pondělí',
'ut' => 'Úterý',
'st' => 'Středa',
'ct' => 'Čtvrtek',
'pa' => 'Pátek',
];
$form->addCheckboxListAssoc('dny', 'Vyber dny', $arr);
$form->addSubmit('submit', 'Odeslat');
$form->onSuccess[] = function (Form $form) {
bdump($form->getValues());
};
return $form;
}
Tak ti dump bude házet výsledky přesně takové, jaké chceš. :)
Samozřejmě se hodí přetížit ještě metody setValue
,
setDefaultValue
, getRawValue
atp., podle
použití.
Editoval Bulldog (11. 5. 2022 17:59)
- Polki
- Člen | 553
@Bulldog Ještě jsi zapomněl zmínit, že pokud používá nad
formulářem i funkci addContainer
, tak musí podědit i tu, aby
container uměl funkci addCheckboxListAssoc
.
Na to je nejlepší pak použít traitu, která tuto metodu bude přidávat a tuto použít jak ve formuláři, tak v containeru