rozšíření Todolistu z quickstartu o editaci úkolů
- honorguard
- Člen | 9
Zdravím,
s frameworkem se učím teprve krátce a jelikož mi příliš nepomáhá
opisovat zdrojáky z tutorialu a uznávat že až na pár nepřesností to
funguje, potřebuji něco „vymyslet sám“. Řekl jsem si že rozšířit
základní aplikaci z quickstartu o editaci by nemělo být nic složitého,
ale zasekl jsem se na předvyplnění formuláře hodnotamy z tabulky.
Do souboru TodolistPresenter.php jsem přidal funkce
public function actionEdit($id) {
}
public function renderEdit() {
}
A ještě před ně o poznání důležitější
public function createComponentEditForm($id) {
$todo = $this->model->findTodo($id);
$form = new Nette\Application\UI\Form;
$form->addText('text', 'Úkol', 60, 100)
->addRule(Form::FILLED, 'Musíte vyplnit text!')->setDefaultValue($todo->text);
$form->addSubmit('save', 'Uložit');
$form->addSubmit('back', 'Zpět')->setValidationScope(NULL);
$form->onSuccess[] = callback($this, 'processEditForm');
return $form;
}
Samozřejmě jsem si vytvořil ještě soubor edit.phtml a přidal ještě odpovídající akce.
V případě že spustím editační formulář však obdržím hlášku že na řádku kde je setDefaultValue dělám objekt z proměnné která objekt není. To mi nehrálo a tak jsem tam zkusil jako základní hodnotu vložit jen samotné $id, abych věděl jestli se dobře předává proměnná – a ve formuláři mám místo předaného id v políčku s textem nápis „editForm“.
Na editační formulář odkazuji pomocí kódu
<a href="{link edit $todo->id}">editovat</a>
tento odkaz je v souboru show.phtml.
Poradí mi někdo co dělám špatně? Určitě to bude nějaká nad slunce jasná začátečnická chyba…
- 22
- Člen | 1478
čau, problém, který vidím na první pohled je tady:
public function createComponentEditForm($id) {}
Komponentě takto nelze předat parametr, protože v konstruktoru očekáva něco jiného viz. API
takže id tam musíš dopravit jinak, z hlavy mě napadají minimálně tyto 2 možnosti
- naplnit data do formu v action metodě:
public function actionEdit($id) {
$todo = $this->model->findTodo($id);
$form = $this->getComponent('editForm');
$form['text']->setValue($todo->text);
}
- získat id z URL
public function createComponentEditForm() {
$todo = $this->model->findTodo($this->getParam('id'));
$form = new Nette\Application\UI\Form;
$form->addText('text', 'Úkol', 60, 100)
->addRule(Form::FILLED, 'Musíte vyplnit text!')->setDefaultValue($todo->text);
$form->addSubmit('save', 'Uložit');
$form->addSubmit('back', 'Zpět')->setValidationScope(NULL);
$form->onSuccess[] = callback($this, 'processEditForm');
return $form;
}
Editoval 22 (7. 9. 2011 2:54)
- powercz
- Člen | 12
Zdravím,
už továrničku máš špatně napsanou, použij:
protected function createComponentEditForm()
22 napsal(a):
dovolil bych si trochu upravit tvé řešení:
public function actionEdit($id) {
$todo = $this->model->findTodo($id);
$this->getComponent('editForm')->setDefaults($todo);
}
případně
public function createComponentEditForm() {
$todo = $this->model->findTodo($this->getParam('id'));
$form = new Nette\Application\UI\Form;
$form->addText('text', 'Úkol', 60, 100)
->addRule(Form::FILLED, 'Musíte vyplnit text!');
$form->addSubmit('save', 'Uložit');
$form->addSubmit('back', 'Zpět')->setValidationScope(NULL);
$form->onSuccess[] = callback($this, 'processEditForm');
$form->setDefaults($todo);
return $form;
}
- honorguard
- Člen | 9
Díky všem, jedn z popsaných metod určitě použiju. Aspoň vím jak se proměnné předávají a nepředávají.
Co znamená to „protected“ před slovem function? Mám to použít i u vkládacího formuláře a proč?
Mám v php napsané své vlastní CMS a programoval jsem ho (bohužel) úplně jiným stylem a tak mám v MVS a Nette vůbec trošku hockey. Snad jednou přijde doba kdy taky budu moct lidem poradit, ale asi to bude chvilku trvat…
- VaKvas
- Začátečník | 111
honorguard napsal(a):
Co znamená to „protected“ před slovem function? Mám to použít i u vkládacího formuláře a proč?
Udava se tim pristupnost.
Protected znamena, ze na jeji metody a atributy muze jen samotna trida a jeji
pribuzni (potomci, predci).
Pak je jeste private a to to muze jen samotna trida. No a public je pro vsechny..
- honorguard
- Člen | 9
Význam slov public a private jsem znal, ale protected pro mě bylo záhadou, děkuji.
Zcela „nečekaně“ jsem se zasekl hned u dalšího kroku – uložení hodnot do databáze.
V souboru TodoManager mám funkci
public function editTodo(Todo $todo) {
return dibi::query('UPDATE [tasks]', (array) $todo);
}
Dibi je pro mě taky novinka, netuším proč je jméno tabulky v hranatých závorkách, ani co znamená slovo array v závorce, je to víceméně upravená jiná funkce z quickstartu a zaručeně je tam něco zásadního špatně, protože mi to píše chybu SQL syntaxe.
//EDIT
za název tabulky jsem přidal ještě slovo SET a žádná chyba – ale zase
se mi změnily všechny záznamy v tabulce :-D. Možná je na čase si
přečíst něco o tom jak se používá dibi…
//EDIT
Takže kód jsem upravil následovně
public function editTodo(Todo $todo) {
return dibi::query('UPDATE [tasks] SET', (array) $todo, 'WHERE [id]=%i', $todo->id);
}
Když $todo->id natvrdo nahradím číslem funguje to, jediný problém je
jak správně předat id, protože tento zápis nefunguje (chyba Undefined
property: todo::$id), ale text se normálně předá a uloží – napadá
někoho kde je problém?
Předem dík
Editoval honorguard (7. 9. 2011 15:24)
- powercz
- Člen | 12
honorguard napsal(a):
netuším proč je jméno tabulky v hranatých závorkách…
Kvůli různým databázím, pro MySQL se vygeneruje dotaz
// UPDATE `tasks` SET...
pro ODBC
// UPDATE [tasks] SET...
(array) znamená přetypování, object $todo se přetypuje na pole, aby jej bylo možné uložit do databáze. Mrkni se do Dibi dokumentace
A proč se ti změnily všechny záznamy v tabulce? :D Neurčil jsi, který řádek se má updatovat (WHERE), tak se updatují všechny :)
- honorguard
- Člen | 9
Aaaa, dibi umí pracovat s více typy databází :-D. Dobrá vychytávka, že jsem to nepoužíval dřív… teď už jen vědět jak tam dostat to id, ale možná už chápu proč je tam ta chyba – jestli se todo přetypovalo na pole tak to totiž není objekt… pokud je teda moje teorie správná :-D.
čili, jak správně předat do dotazu id?
- powercz
- Člen | 12
honorguard napsal(a):
čili, jak správně předat do dotazu id?
Předpokládám že máš id upravovaného řádku uložené v $todo, vyřešil bych to takto:
public function editTodo(Todo $todo) {
$todo = (array) $todo;
return dibi::query('UPDATE [tasks] SET', $todo, 'WHERE todo_id=%i',$todo['todo_id']);
}
Pokud ne, tak si předej $todo_id do metody editTodo(Todo $todo, $todo_id) …
- honorguard
- Člen | 9
Zkoušel jsem to udělat tak jak radí Powercz, ale neuspěl jsem, nakonec jsem to vyřešil předáním id v argumentech v metodě processEditForm, kterou uvádím níže pro doplnění:
public function processEditForm(Nette/Application/UI/Form $form) {
if($form['save']->isSubmitedBy()) {
$this->flashmessage('Úkol byl změněn.');
$values = $form->getValues();
$todo = new Todo;
$todo->text = $values['text'];
$todo_id = $this->getParam('id') //tady získám id z adresy
$this->model->editTodo($todo, $todo_id);
}
$this->redirect('Todolist:show');
}
S tím získáním $id z adresy a předáním v argumentech to funguje výborně, takže všem díky za pomoc.
Ještě jeden začátečnický dotaz – jak v následujícím příkladu v metodě onmouseover použít makro pro předání proměnné $basePath?
<img src="{$basePath}/images/adresa_obrazku.gif" onmouseover="this.src='{$basePath}/images/obrazek.gif'" />
Zkoušel jsem nastavit podle quickstartu dvojitý zápis závorek, ale vždycky se mi kolem té adresy v $basePath objeví nějaké znaky se slovy quote. Jak vyřešit tento zápis? Případně má Nette nějaké vlastní prostředky jak změnit obrázek po najetí myší a při odjetí zase na jiný obrázek?
Předem díky