Předávání ID formuláři pro editaci záznamu
- DETAIL
- Člen | 33
Ahoj přečetl jsem si snad všechnu dokumentaci k forms i tady na foru a
pořád nechápu jednu věc.
Jak správně předávat ID záznamu který chci editovat.
Mám handle přes který nastavím ID a přes snippet vykreslím form, to
funguje správně, problém je, když se ten formulář odešle a neprojde
validací, protože to ID už neexistuje. Všude se píše, že mám použít
action metodu, ale nevím co je tím myšleno, protože formulář se odešle
přes POST s ID=ID_fomuláře a nevím jak bych měl docílit, aby volal
action($ID). Přes addHiden to dělat nechci a ani jsem to nezkoušel, jestli by
to pomohlo.
Obešel jsem to sice přes session, které si nastavím v handle, ale tj
určitě špatné řešení.
Zatím to mám všechno mimo továrnu, protože k nim jsem se ještě
nedostal.
Cílem je vypsat hodnoty z DB do formuláře, možnost jejich úpravy a
následné odeslání zpět. A někde právě musí být ID záznamu.
Jo a mám na editaci a vytvoření extra dva formuláře… což jsem zjistil,
že být nemusí, ale určitě to teď ničemu nevadí.
Děkuji za pomoc
- n3t
- Člen | 37
Action metoda je popsaná v dokumentaci zde.
V podstatě stačí jen přidat parametr id k této metodě a nějak si jej zpracovat a použít při vytváření formuláře:
final class MyPresenter extends BasePresenter
{
private $editItem = null;
public function actionEdit(?int $id)
{
if ($id)
$this->editItem = $this->database->table('...')->get($id);
}
protected function createComponentForm(): Form
{
return $this->formFactory->create($this->editItem);
}
}
- Kamil Valenta
- Člen | 822
DETAIL napsal(a):
Přes addHiden to dělat nechci a ani jsem to nezkoušel, jestli by to pomohlo.
Proč nechceš? Pokud se ten form přegenerovává ve snippetu, tak se mi to zdá jako nejlepší řešení. Cesta přes session selže ve chvíli, kdy si otevřu stejnou stránku v druhém tabu…
- DETAIL
- Člen | 33
Ale hidden se dá obejít přes editaci HTML ne? Jako stejně to potom kontroluji jestli je fakt vlastníkem, ale.. @KamilValenta
Action metoda vím k čemu slouží, jenom jsem nepochopil přesně ten návod co je na stránkách na to předávání ID (Jak předávat id při editaci záznamu). Problém je, že mám modal, což jsem tam zapomněl napsat a pak musím řešit tyto problémy, kdyby to byla extra stránka jenom s tím formulářem, tak se to dá předávat přes to querry no.
Spíš se ještě zkusím podívat jak přesně fungují ty formfactory.
Stejně jsem pořád nezjistil, jestli je dobré předávat přímo ty ID co jsou v DB, jak přes to hidden, tak v URL. Děkuji za objasnění ještě tohoto.
Kamil Valenta napsal(a):
Cesta přes session selže ve chvíli, kdy si otevřu stejnou stránku v druhém tabu…
A ještě prosím tě jak jsi to myslel? @KamilValenta Nevím přesně co by se rozbilo, protože session ID zůstane ne?
- DETAIL
- Člen | 33
A jak to vlastně potom vypadá v kódu, když použiji hidden?
Protože sice si to ID uložím do formuláře, ale to ID je potom ještě
jednou potřeba pro kontrolu formuláře na serveru.
Jelikož já tam načítám data z DB a pak kontroluji, jestli hodnoty co jsou
v selectu sedí s DB a ty jsou podle toho ID záznamu.
Možná jsem se jenom do toho zamotal… :(
protected function createComponentFormEditRecord(): Form
{
$zaznamDB = $this->denikManager->get($this->ID_zaznamu)->fetch();
$form = new Form;
$typyDB = $this->denikManager->getAllTypes()->fetchAll();
$typy = array( -1 => "Vyberte typ úkonu"); //toto jsem už zjistil, že jde udělat jinak
$typ_ukonu = $zaznamDB->ID_typ_ukonu;
foreach ($typyDB as $typ)
{
$typy[$typ->ID_typ_ukonu] = $typ->typ_ukonu_nazev;
}
$form->addSelect('type', 'Typ:', $typy)
->setRequired('Prosím vyberte typ úkonu')
->addRule(Form::NOT_EQUAL, 'Prosím vyberte typ úkonu', -1)
->setDefaultValue($typ_ukonu);
//čas nemá jít editovat, má tam být jenom jako readonly
$casy[$zaznamDB->ID_mereni_zar] = $zaznamDB->cas->format("d.m.Y - H:m");
$ID_mereni_zar = $zaznamDB->ID_mereni_zar;
$form->addSelect('time', 'Čas měření:', $casy)
->setRequired('Prosím vyberte čas úkonu')
->addRule(Form::NOT_EQUAL, 'Prosím vyberte čas úkonu', -1)
->setDisabled()
->checkDefaultValue(false)
->setDefaultValue($ID_mereni_zar);
$record = $zaznamDB->popis_ukonu;
$form->addTextArea('record', 'Poznámka:')
->setHtmlAttribute('placeholder', 'Poznámka')
->addRule($form::MIN_LENGTH, 'Hodnota v poli "Poznámka" není správná: minimum je %d znaků' , 5)
->setHtmlAttribute('rows', '3')
->setRequired('Prosím zadejte popis úkonu')
->setDefaultValue($record);
$form->addHidden('ID_zaznamu', $this->ID_zaznamu);
$form->addProtection();
$form->addSubmit('edit', 'Změnit');
$form->onSuccess[] = [$this, 'formEditRecordSucceeded'];
return $form;
}
Problém tedy nastává při odeslání formuláře, kdy se nemůže provést
$zaznamDB = $this->denikManager->get($this->ID_zaznamu)->fetch();
Jediné co vlastně potřebuji zkontrolovat je record a type.
Editoval DETAIL (21. 4. 2021 15:56)
- Kamil Valenta
- Člen | 822
Pokud zvažuješ předávání z URL do actiony, tak bych neviděl problém v možnost podvrhnout to v hiddenu. Ba naopak, přepsat ID v URL zvládne každý Franta, editovat DOM zvládne spíš až poučený Franta. Tak jako tak to musíš v dalším kroku validovat.
Spíš mi není jasné, když ten formulář překresluješ ve snippetu, jak do toho chceš zapojit URL. Ta je přeci stejná. Takže si překreslíš form, v hiddenu si předáš ID a v dalším kroku na něj sáhneš do values, zvaliduješ ho a zpracuješ.
Ad sessions: představ si situaci, kdy si totožnou stránku otevřu ve dvou tabech. V jednom si kliknu na editaci věty s ID=1 (překreslí se snippet a do sešny se poznačí ID=1). Form neodesílám. V druhém tabu si kliknu na editaci věty s ID=2 (překreslí se mi snippet a do sešny se poznačí ID=2). Form neodesílám. Vrátím se do prvního tabu a form odešlu. Odchází mi values pro ID=1, ale updatne se mi věta s ID=2, protože v sešně bylo jako poslední ID=2.
Když si to budeš tahat v hiddenu, tak se to nestane, protože do handleru formuláře tě přinde vždy konzistentní „balíček“ dat (tedy údaje + správné id).
- DETAIL
- Člen | 33
Dík za tu session, jj na to jsem zapomněl, že může takto zkusit něco
editovat. @KamilValenta , ale asi by to šlo pořešit přes hidden a
párovat to s tou session, ale to už rovnou můžu použít ten hidden
samostatně :D
Já do toho formuláře nechci zapojit URL, chci jen aby ten formulář fungoval
:D
Protože i když to dám do hidden, tak pořád mám problém s validací na
serveru, kdy to ID není k dispozici a tak mi to vyhodí chybu, že záznam
neexistuje.
Editoval DETAIL (21. 4. 2021 18:29)
- Kamil Valenta
- Člen | 822
Když ho dáš do hidden, tak ho najdeš ve $values->id (pokud hidden měl
jméno id), není důvod, aby jen tak nebyl k dispozici.
Ukaž variantu s hiddenem.
- DETAIL
- Člen | 33
Kamil Valenta napsal(a):
Když ho dáš do hidden, tak ho najdeš ve $values->id (pokud hidden měl jméno id), není důvod, aby jen tak nebyl k dispozici.
Ukaž variantu s hiddenem.
Však to v tom kodu je :D @KamilValenta
Ta hodnota určitě dostupná je, ale já se ani nedostanu k té funkci co se
má volat po odeslání, protože neprojde validace formuláře.
Editoval DETAIL (21. 4. 2021 20:04)
- DETAIL
- Člen | 33
Vážně se nenajde někdo, kdo by mi poradil jak na ten modal s formulářem? Ten hidden tam mám vložený, ale pořád to neřeší ten problém s validací co dělá nette po odeslání formuláře. Hlavní je, že tady na foru je o tom asi 10 vláken, ale nikde není tento problém bohužel vyřešen (nebo jsem to nepochopil), i když věřím, že to musí nějak jít.
Editoval DETAIL (22. 4. 2021 23:56)
- Kamil Valenta
- Člen | 822
Ach jo. Tak znovu. Hidden máš. Ok. Odkud se bere $this->ID_zaznamu? Naplní se z values při odeslání formu? Kde na to id ve $values saháš? Psal jsi, že to v tom kódu je, já to tam nikde nevidím… Co znamená, že neprojde validace?
- DETAIL
- Člen | 33
Ono je to ale jedno, protože se to sem ani nedostane @Ages
public function formEditRecordSucceeded($data):void
{
$this->denikManager->update($data->ID_zaznamu, $data->type, $data->record);
$this->flashMessage("Záznam byl upraven", "success");
$this->redirect('Homepage:');
}
Editoval DETAIL (23. 4. 2021 1:44)
- DETAIL
- Člen | 33
Kamil Valenta napsal(a):
Ach jo. Tak znovu. Hidden máš. Ok. Odkud se bere $this->ID_zaznamu? Naplní se z values při odeslání formu? Kde na to id ve $values saháš? Psal jsi, že to v tom kódu je, já to tam nikde nevidím… Co znamená, že neprojde validace?
$this->ID_zaznamu nastavuji přes handle, který je na tlačítku co
otevírá modal.
Co znamená, že neprojde validace?
Jak jsem už psal, jelikož není dostupné to ID v $this->ID_zaznamu, tak
tohle se nemůže načíst a zkontrolovat ten formulář jestli má ty hodnoty
správné
$zaznamDB = $this->denikManager->get($this->ID_zaznamu)->fetch();
Jediný problém je, že ID záznamu , už není dostupné při ověření a
nevím přesně jaký je postup použítí toho hidden, protože hidden
používám jenom v succeed a nevím jak k němu přistoupit v samotném
formuláři. Jestli to jde, tak potom asi stačí dát na začátek jeden
if…
Kdyby to byla normální action stránka tak to ID beru z querry, ale tady to
nejde udělat.
Editoval DETAIL (23. 4. 2021 1:53)
- Kamil Valenta
- Člen | 822
Proto se ptám, kde se nastavuje hodnota pro ID_zaznamu, protože to nikde
vidět není.
Ona může pocházet buď z parametru handlu, nebo z postu (v hiddenu). A ty
si musíš vypodmínkovat, kdy ji odkud budeš brát.
Z toho hiddenu, pokud ještě Form není připojený, to asi budeš muset
dostat přímo z requestu, něco jako:
if (empty($this->ID_zaznamu) && isset($this->httpRequest->getPost()['ID_zaznamu'])) {
$this->ID_zaznamu = (int) $this->httpRequest->getPost()['ID_zaznamu'];
}
$zaznamDB = $this->denikManager->get($this->ID_zaznamu)->fetch();
- Ages
- Člen | 128
Jak píše @KamilValenta → musíš si to ID nastavit, nevím jak se ti jmenuje ta metoda pro editaci, ale musíš tam doplnit to nastavení ID, jen pozor pokud to máš v render metodě, tak to je pozdě a nebude ti to fungovat viz „:https://doc.nette.org/…n/presenters#…“
public function actionEdit(int $ID_zaznamu): void
{
$this->ID_zaznamu = $ID_zaznamu
…
}
btw: také tu metodu musíš volat s tím parametrem, ale to je snad jasné :)