Dynamické přídání položek do formuláře
- Croc
- Člen | 270
Zdravím,
v seznamování s Nette jsem narazil na další „problém“. Řeším teď
následující:
- Základní formulář bude mít 2 inputy – Datum a input s číslem. Do DB budu ukládat číselnou hodnotu a datum kdy byla naměřena.
- Potřebuji, aby se pomocí tlačítka přidal další pár inputů. Těchto párů může být 1-N .
- Potřebuji tedy vyřešit dynamické přidávání páru inputů (i jejich odebrání ??) a následné zpracování pro uložení do DB.
- Při načtení formuláře potřebuji zobrazit 0-N vyplněných párů inputů (data z DB).
Procházel jsem forum a narazil jsem na Kdyby/Replicator.
Chci se tedy zeptat, jestli je Kdyby/Replicator ideální řešení na můj případ a hlavně jestli je použitelný s poslední verzí Nette (2.3.4).
Díky moc
- romiix.org
- Člen | 343
Akým príkazom sa to snažíš nainštalovať?
composer require kdyby/forms-replicator:@dev
- Croc
- Člen | 270
Zkouším implementovat následující:
<?php
namespace App\Forms;
use Nette,
App\Model\UserManager,
Nette\Application\UI\Form,
App\Model,
Nette\Forms\Container,
Nette\Forms\Controls\SubmitButton;
class WeightFormFactory extends Nette\Object
{
/** @var Nette\Security\User */
public $user;
/** @var \App\Model\UserManager */
public $userManager;
/** @var \App\Model\UtilsManager */
public $utilsManager;
public function __construct(UserManager $userManager, Nette\Security\User $user, Model\UtilsManager $utilsManager)
{
$this->userManager = $userManager;
$this->user = $user;
$this->utilsManager = $utilsManager;
}
/**
* @return Form
*/
public function create($id)
{
$form = new Form;
$removeEvent = callback($this, 'WeightFormRemoveElementClicked');
// name, factory, default count
$users = $form->addDynamic('users', function (Container $user) use ($removeEvent) {
$user->addText('date','Datum:');
$user->addSubmit('remove', 'Remove')
->setValidationScope(FALSE) # disables validation
->onClick[] = $removeEvent;
}, 1);
$users->addSubmit('add', 'Add')
->setValidationScope(FALSE)
->onClick[] = callback($this, 'WeightFormAddElementClicked');
$form->addProtection('Vypršel časový limit, odešlete formulář znovu');
$form->addSubmit('send', 'Odeslat');
$form->onSuccess[] = array($this, 'formSucceeded');
return $form;
}
public function formSucceeded($form, $values)
{
//.....
}
public function WeightFormAddElementClicked(SubmitButton $button)
{
$users = $button->parent;
// count how many containers were filled
if ($users->isAllFilled()) {
// add one container to replicator
$button->parent->createOne();
}
}
public function WeightFormRemoveElementClicked(SubmitButton $button)
{
// first parent is container
// second parent is it's replicator
$users = $button->parent->parent;
$users->remove($button->parent, TRUE);
}
}
Ať kliknu na tlačítko Add, Remove nebo Odeslat, dostanu následující chybu:
Notice
Undefined property: Nette\Utils\ArrayHash::$temp
File: G:\workspace\vendor\nette\utils\src\Utils\ArrayHash.php:77
67: $this->$key = $value;
68: }
69:
70:
71: /**
72: * Returns a item.
73: * @return mixed
74: */
75: public function offsetGet($key)
76: {
77: return $this->$key;
78: }
79:
80:
81: /**
Bohužel netuším kde je chyba. Postupoval jsem dle návodu.
EDIT: Vypadá to že tlačítka Add a Remove mají funkci odeslání formuláře. Zkusím zjistit více.
Editoval Croc (23. 8. 2015 12:35)
- Croc
- Člen | 270
To už jsem vyřešil. Opravdu jsem přistupoval k $values->temp ve formSucceeded.
Částečně jsem to rozchodil pomocí tohoto vlákna.
Zobrazí se mi nastavený počet inputů, můžu je mazat a zase přidávat, ale nemůžu jich přidat více než byla defaultní hodnota, což je problém.
Kód mám nyní takhle:
$form = new Form;
$removeEvent = callback($this, 'WeightFormRemoveElementClicked');
// name, factory, default count
$users = $form->addDynamic('users', function (Container $user) use ($removeEvent) {
$user->addText('date','Datum:');
$user->addSubmit('remove', 'Remove')
->setValidationScope(FALSE) # disables validation
->addRemoveOnClick();
}, 1);
$users->addSubmit('add', 'Add')
->setValidationScope(FALSE)
->addCreateOnClick(/*parametr TRUE umozni pridat radky dopredu, aniz by musely byt vyplneny*/);
$form->addProtection('Vypršel časový limit, odešlete formulář znovu');
$form->addSubmit('send', 'Odeslat');
$form->onSuccess[] = array($this, 'formSucceeded');
return $form;
}
Už to funguje :) Nepřečetl jsem si pořádně dokumentaci a použil jsem variantu, kdy musí být první pole vyplněné aby šlo přidat nové. Pokud tedy vyplním první pole a chci přidat nové, vše funguje jak má :)
Editoval Croc (25. 8. 2015 10:44)