Formulář v komponentě – ztráta ID
- MW
- Člen | 626
Zdravím a prosím o radu – vysvětlení.
Mám formulář v komponentě, který odesílám Ajaxem. Vše funguje až do doby, kdy tam přidám onu kontrolu na $id, protože chci použít form pro vkládání i editaci uživatelů a při editaci bude heslo nepovinné, pro vkládání povinné.
Chová se to tak, že pokud zadám heslo je vše ok, form se odešle a uloží. Pokud nezadám heslo, formulář se neodešle a ani to nedumpne nějakou chybu.
Snažím se to krokovat a jeví se mě to tak, že po kliknutí na submit se nejprve překresluje formulář, kde je ale v tu chvíli $id null …
Form vytvářím klasicky přes továrnu.
Co mě prosím uniká? Moc díky!
/**
* @return Form
*/
public function createComponentForm() {
$form = $this->formFactory->create();
$form->getElementPrototype()->class('ajax');
$form->addHidden('id');
$form->addText('name', 'Celé jméno: ')
->setRequired('Zadejte celé jméno.');
$form->addText('username', 'Uživatel: ')
->setRequired('Zadejte uživatelské jméno.');
$id = $this->getPresenter()->getComponent('usersGrid')->getParameter('id');
If (!$id) {
$form->addPassword('password', 'Heslo: ')
->setRequired('Zadejte heslo');;
$form->addPassword('passwordVerify', 'Heslo pro kontrolu: ')
->addConditionOn($form["password"], Form::FILLED)
->addRule(Form::EQUAL, "Hesla se musí shodovat!", $form["password"]);
} else {
$form->addPassword('password', 'Heslo: ');
$form->addPassword('passwordVerify', 'Heslo pro kontrolu: ')
->addConditionOn($form["password"], Form::FILLED)
->addRule(Form::EQUAL, "Hesla se musí shodovat!", $form["password"]);
}
$form->addSelect('role', 'Oprávnění', array('user' => 'user', 'admin' => 'admin'));
$form->addSubmit('send', 'Uložit');
$form->onSuccess[] = array($this, 'formSucceeded');
if ($id) {
$r = $this->usersModel->getUsersTable()->where('id', $id)->fetch();
if (!$r) {
throw new Nette\Application\BadRequestException;
}
$form->setDefaults($r);
}
return $form;
}
Editoval MW (31. 1. 2017 15:11)
- MW
- Člen | 626
Přišel jsem na toto.. co vy na to? Lze to takto?
Ta komponenta gridu to ID asi ztrati…
public function createComponentForm() {
$form = $this->formFactory->create();
$form->getElementPrototype()->class('ajax');
$form->addHidden('id');
$form->addText('name', 'Celé jméno: ')
->setRequired('Zadejte celé jméno.');
$form->addText('username', 'Uživatel: ')
->setRequired('Zadejte uživatelské jméno.');
If (empty($form['id'])) { // **************************tato podmínka
$form->addPassword('password', 'Heslo: ')
->setRequired('Zadejte heslo');;
$form->addPassword('passwordVerify', 'Heslo pro kontrolu: ')
->addConditionOn($form["password"], Form::FILLED)
->addRule(Form::EQUAL, "Hesla se musí shodovat!", $form["password"]);
} else {
$form->addPassword('password', 'Heslo: ');
$form->addPassword('passwordVerify', 'Heslo pro kontrolu: ')
->addConditionOn($form["password"], Form::FILLED)
->addRule(Form::EQUAL, "Hesla se musí shodovat!", $form["password"]);
}
$form->addSelect('role', 'Oprávnění', array('user' => 'user', 'admin' => 'admin'));
$form->addSubmit('send', 'Uložit');
$form->onSuccess[] = array($this, 'formSucceeded');
$id = $this->getPresenter()->getComponent('usersGrid')->getParameter('id');
if ($id) {
$r = $this->usersModel->getUsersTable()->where('id', $id)->fetch();
if (!$r) {
throw new Nette\Application\BadRequestException;
}
$form->setDefaults($r);
}
return $form;
}
Editoval MW (31. 1. 2017 15:41)
- Šaman
- Člen | 2665
To $id
musíš komponentě předat, nejspíš v
action
metodě. Jen formulář si ho získá z POSTu sám (pokud
odeslaná data to $id
obsahovala).
A načítat nějaká data z jiné komponenty není vůbec hezké – pokud
spolu maji úzce spolupracovat, tak je lepší je obalit nějakou
nadkomponentou. Ale jestli to dobře chápu, tak ten formulář nyní vyžaduje,
aby byl k presenteru připojený (a správně nastavený) i Grid, jinak nebude
fungovat. To je typická ukázka skryté závislosti.
- MW
- Člen | 626
Asi ano :)
Mám v presenteru obě komponenty :
public function createComponentUsersGrid() {
return $this->usersGridControlFactory->create();
}
public function createComponentEditForm() {
return $this->userEditFormControlFactory->create();
}
no a v šabloně gridu pak lovím
{control $presenter->getComponent('editForm')}
Jak bych to měl správně dát dohromady? .. přiznám se, že se mě to taky nelibí..
Snažím se v Ublaboo gridu udělat editaci v modálním okně, což mě
teď funguje dobře, ale rád bych to měl líp :)
Ted jsem obsluhu modálů přidal do komponenty Gridu, ale važně blbě
(nepřehledně) se posílají data mezi gridem, formulářem, modelem a ted
i něco do presenteru :/
Mohu poprosit o nějaký vzor, jak to spojit?
Moc díky!
Editoval MW (31. 1. 2017 16:41)
- CZechBoY
- Člen | 3608
Připojit ke Gridu komponentu MujModal → třeba v actionXXX připojíš přes addComponent komponentu mujModal + nějak připojit do template
class MujPresenter extends UI\Presenter
{
public function actionDefault()
{
$modal = $this->modalFactory->create();
$this['mujGrid']->addComponent($modal, 'modal');
$this['mujGrid']->setTemplateFile('GridModal.latte');
}
protected function createComponentMujGrid()
{
return $this->gridFactory->create();
}
}
GridModal.latte
{extends $original_template}
{control modal}
Editoval CZechBoY (31. 1. 2017 17:54)
- MW
- Člen | 626
Upravi jsem to, ale stále mě dobře nefunguje podmínka ve formuláři
If(is_null($form['id']))
to id je stále null :/.. tedy se ten formulář při odeslání nějak znovu rendruje a id se do něj dostane až pozdě… proč?
Presenter:
public function actionDefault($id) {
$this->id = $this->getComponent('usersGrid')->getParameters('id');
$this['usersGrid']->addComponent($this->userEditFormControlFactory->create(), 'editForm');
if($this->id) {
$r = $this->userModel->getUsersTable()->where('id', $this->id)->fetch();
if (!$r) {
throw new Nette\Application\BadRequestException;
}
$this['usersGrid-editForm-form']->setDefaults($r);
}
}
public function setId($id) {
$this->id = $id;
}
Komponenta formu:
lass UserEditFormControl extends Control {
/** @var FormFactory */
private $formFactory;
public function __construct(FormFactory $formFactory) {
$this->formFactory = $formFactory;
}
/**
* @return Form
*/
public function createComponentForm() {
$form = $this->formFactory->create();
$form->getElementPrototype()->class('ajax');
$form->addHidden('id');
$form->addText('name', 'Celé jméno: ')
->setRequired('Zadejte celé jméno.');
$form->addText('username', 'Uživatel: ')
->setRequired('Zadejte uživatelské jméno.');
If(is_null($form['id'])) {
$form->addPassword('password', 'Heslo: ')
->setRequired('Zadejte heslo');;
$form->addPassword('passwordVerify', 'Heslo pro kontrolu: ')
->addConditionOn($form["password"], Form::FILLED)
->addRule(Form::EQUAL, "Hesla se musí shodovat!", $form["password"]);
} else {
$form->addPassword('password', 'Heslo: ');
$form->addPassword('passwordVerify', 'Heslo pro kontrolu: ')
->addConditionOn($form["password"], Form::FILLED)
->addRule(Form::EQUAL, "Hesla se musí shodovat!", $form["password"]);
}
$form->addSelect('role', 'Oprávnění', array('user' => 'user', 'admin' => 'admin'));
$form->addSubmit('send', 'Uložit');
$form->onSuccess[] = array($this, 'formSucceeded');
return $form;
}
public function formSucceeded(Form $form, $values) {
unset($values->passwordVerify);
$this->getPresenter()->getComponent('usersGrid')->saveData($values);
}
public function render() {
$this['form']->render();
}
}
V komponentě gridu mám handle:
public function handleEditModal($id) {
$this->getPresenter()->setId($id);
$this->redrawControl('editForm');
$this->redrawControl('showModal');
}
- CZechBoY
- Člen | 3608
Bude řízený tak napůl. ID do presenteru „předá“ ten handle.
Něco jako tohle (píšu z founu)
Komponenta
function handleEditForm($id)
{
$this['form']->setAction($this->getPresenter()->link('edit', ['id' => $id]));
// Redraw atd
}
Presenter
function actionEdit($id)
{
$this['form']->setId($id);
}
- CZechBoY
- Člen | 3608
Ajo, asi jsem se v tom zamotal :D
Takže znova. Pro pochopení to radši projdeme celý znova :-)
V actionDefault
vytváříš grid pro seznam uživatelů –
tady vytvoříš grid, formulář a formulář připojíš ke gridu (v tomto
momentě ještě nevíš jestli použiješ/odešleš add nebo
edit variantu formuláře).
V šabloně potom přidáš nějaký modální okno s editačním formulářem
(to se načte ajaxově), parametr je dynamický.
Handle nastaví akci formuláře na edit, id => $id
.
V actionEdit($id)
připojíš form zase ke gridu, ale nastavíš
ještě ID formuláři přes to ->setId($id)
.
Takhle by to snad mohlo jet… ale je možný že jsem něco nedomyslel nebo zbytečně zkomplikoval.
- MW
- Člen | 626
Už ti rozumím, moc díky!
Ale stejně mě není jasny proč se děje to, že form, který je naplněný
přes setDefault a obsahuje všechny data, se při odeslaní znovu sestavuje ale
už nezná svoje pův. hodnoty – viz ona podmínka s $form[‚id‘]..
Přijde mě to jen děsně složity.. :) To mě fakt nutí udělat dva formuláře.