Checkbox u každého prvku vytaženého z databáze
- Jakub
- Člen | 30
Ahoj,
řeším takový problém, se kterým si moc nevím v Nette rady. Vytahuji z databáze záznamy a vypisuji je na stránku (jedná se o příchozí zprávy, stejně jako v emailu). Potřebuji ke každé zprávě přidat checkbox, abych mohl následně doplnit funkcionality jako „Smazat vybrané“, „Přesunout vybrané do archivu“ apod.
Jak to udělat co nejefektivněji? Konkrétněji – nevím si rady s tím, jak vytvořit ke každému vytaženému záznamu ten checkbox. Záznamy vytahuji v metodě render, formulář tvořím přes komponenty.
Děkuji za tipy.
- srigi
- Nette Blogger | 558
Formular mozes v tovarnicke vytvarat plne dynamicky. Budem vychadzat z toho, ze kazda sprava ma nejaky perex a ID. Metodu render nebude treba, lebo perex sa vlozi do formulara.
Presenter
class BlablablaPresenter extends Presenter
{
protected function createComponentFormNews($name)
{
$form = new AppForm($this, $name);
$form->addGroup('Newsky');
$news = Model::getAll();
foreach ($news as $newie) {
$form->addCheckbox('newie-' . $newie->id, $newie->perex);
}
$form->addGroup('Akce');
$form->addSelect('action', 'Akce:', array('Smazat', 'Archivovat', 'Skryt'));
$form->addSubmit('dowork', 'Vykonat');
$form->onSubmit[] = ($this, 'SubmittedFormNews');
return $form;
}
// spracovanie
public function SubmittedFormNews(AppForm $form)
{
... $form->values; // spracovanie
...
$this->redirect('Blablbla:'); // po spracovani nezabudnut na redirect!
}
}
Bolo by asi vhodne prehodit label a checkbox vo formulari, aby to vyzeralo k svetu. to bude vyzadovat cca taketo sablony:
templates/Blablabla.default.phtml
{block #content}
{include '@formNews.phtml', form=>$presenter['formNews']}
templates/@formNews.phtml
{control $form begin}
<!-- hidden fields -->
<div n:foreach="$form->getComponents(TRUE, 'Nette\Forms\HiddenField') as $control">{$control->control}</div>
<!-- errors -->
{assign errors => $form->errors}
<ul class="error" n:if="$errors" n:block="#errors">
<li n:foreach="$errors as $error">{$error}</li>
</ul>
<!-- groups -->
<fieldset n:foreach="$form->groups as $group" n:if="$group->controls && $group->getOption('visual')" n:block="#group">
<legend n:ifset="$group->options['label']">{$group->options['label']}</legend>
<p n:ifset="$group->options['description']">{$group->options['description']}</p>
<table n:block="#controls">
<tr {attr class('required', $control->getOption('required'))} n:foreach="$group->controls as $control" n:if="!$control->getOption('rendered')" n:block="#pair">
<td n:block="#control">{!$control->control}{if $control instanceof Checkbox}{!$control->label}{/if}</td>
<td n:block="#label">{if $control instanceof Button || $control instanceof Checkbox} {else}{!$control->label}{/if}</td>
</tr>
</table>
</fieldset>
<!-- non-group -->
{include #controls, group => $form}
{control $form end}
Ta tovarnicka ti vytvori kopec checkboxov s menami newie-ID
,
takze v callbacku na spracovanie si pekne preiterujes cez zaskrtnute checkboxy
a z ich mien pomocou PHP funkcii na pracu so stringami vytiahnes ID. Potom uz
iba v modeli vykonas akciu nad tymi IDckami.
- Jakub
- Člen | 30
Díky za vyčerpávající odpověď, ještě se zeptám – mám nyní v tom rendru také stránkování + ten dotaz na DB je docela složitý (tzn. nevypisuji u zpráv jen perex, ale zhruba 5 informací u každé zprávy). I v takovém případě nebudu ten render již potřebovat? Mám to stránkování dát také do té komponenty formuláře? A jak vypíšu ty další údaje o zprávě?
Děkuji za pomoc!
- srigi
- Nette Blogger | 558
Jakub napsal(a):
mám nyní v tom rendru také stránkování + ten dotaz na DB je docela složitý (tzn. nevypisuji u zpráv jen perex, ale zhruba 5 informací u každé zprávy). I v takovém případě nebudu ten render již potřebovat? Mám to stránkování dát také do té komponenty formuláře? A jak vypíšu ty další údaje o zprávě?
Ano render sa zrusi cely, lebo cela ta obrazovka bude v podstate formular (okrem paginatora). Takze v tovarnicke sa z DB vytiahnu tie newsky, ktore maju byt prave zobrazene. Troska som sa hral v MockFlow, pripravil som wireframe aby to slo lepsie predstavit
Riadok s checkboxom je jeden form
pair (tj. form label & form control) a do labelu sa natrepu vsetky tie
infozz. Treba sa pohrat s jeho HTML kodom. V tom foreach
cykle
v tovarnicke sa vykona cca toto:
foreach ($news as $newie) {
$div = Html::el();
$div->create('strong', $newie->perex);
$subject = Html::el('span')->class(array('subject'))->setText($newie->subject);
$date = Html::el('span')->class(array('date'))->setText($newie->date);
$div->add($subject);
$div->add($date);
$form->addCheckbox('newie-' . $newie->id, $div);
}
Do labelu forulara by sa tak malo vyrenderovat nieco ako
<td class"label"><div><strong>text perex</strong><span class="subject">text subject</span><span class="date">15.6.2010</span></div></td>
treba ale trocha upravit tu custom sablonu formulara, vyhladaj riadok
<td n:block="#label">{if $control instanceof Button || $control instanceof Checkbox} {else}{!$control->label}{/if}</td>
a vymaz ten if (aby sa HTML elementy „dostali k slovu“)
<td n:block="#label">{!$control->label}</td>
K tomu paginovaniu – s uspechom mozes v tovarnicke na zaciatku pouzivat konstrukciu
$page = ($this->getParam('page')) ? (int) $this->getParam('page') : 1;
Pomocou toho si z DB vytiahnes konktretnu „stranku“ (LIMIT, OFFSET) s novinkami a zostavis formular. Na renderovanie potom pouzi VisualPaginator (takze tu metodu render nakoniec budes potrebovat :D)
Pisal som to z hlavy, takze to nemusi fungovat hned na prvykrat!
Editoval srigi (8. 3. 2010 11:25)
- srigi
- Nette Blogger | 558
Jakub napsal(a):
Super, díky! Poslední dotaz – Chystám se ke zprávám přidat ještě další formulář pro jejich filtrování. Mohl bys, prosím, naznačit, jakým způsobem bys toto řešil, když zprávy tahám v té komponentě formuláře? Začínám se do toho zamotávat..
Mockrát děkuji!
Hmm, toto si uz neviem predstavit (funkcnost). Skus pomocou toho MockFlow nakreslit wireframe aby bolo jasne ake ma to filtrovanie fungovat. Alebo to popis slovami.
- Jakub
- Člen | 30
Mělo by to fungovat následovně: Nad tabulkou se zprávami bude jednoduchý formulář – v základní verzi třeba jen s jedním inputem, který bude sloužit k filtrování zpráv podle předmětu. Tzn. když budu chtít najít všechny zprávy, které obsahují v předmětu slovo „Nette“, napíšu do inputu Nette a kliknu na hledej – ve výsledku dostanu vyfiltrované zprávy, které mají v předmětu tento řetězec.
Díky!
- srigi
- Nette Blogger | 558
Premyslal som nad tym – toto je jasny pripad, kde sa pouziju signaly. Komponente posles signal s parametrom (String: ‚Nette‘) a ten na jeho zaklade vygeneruje objekt AppForm a ten vrati. Nova komponenta by tak mala dedit od AppForm a iba ju rozsiris o metodu na prijimanie tohto signalu.
Toto si to vyziada trocha prekopat predchadzajuci kod – komponenta sa bude musiet presunut do vlastneho suboru – v Presenteri sa uz nebude vytvarat objek formu ako doteraz:
protected function createComponentFormNews($name)
{
$form = new AppForm($this, $name);
...
return $form;
}
ale sa presunie do toho potomka AppForm. Takze ta tovarnicka v Presenteri sa prekope asi takto
Presenter
protected function createComponentNews($name)
{
return new NewsControl($this, $name);
}
a prida sa subor s definiciou komponenty:
components/NewsControl.php
class NewsControl extends AppForm
{
// obsluha signalu
public function handleFilternews($input)
{
$news = Model::getByFilter($input);
foreach ($news as $newie) {
...
$this->addCheckbox('newie-' . $newie->id, $newie->perex); // podedili sme od AppForm, takze $this
}
$this->addGroup('Akce');
...
return $this;
}
}
cca takto. Len kua neviem ako nadefinovat callback na spracovanie formu – skus sa pozriet na dokundamentaciu. Popr. si to naprogramuj a skusaj ten callback vseliako definovat. Bude traba tiez nejako nadefinovat to ze klepnutie na „Hledaj/Filtruj“ posle formu signal na horeuvedny handler.
Editoval srigi (9. 3. 2010 17:15)
- Jakub
- Člen | 30
Díky moc za cenné rady! Našel jsem při procházení fóra ještě tohle: https://componette.org/search/?…, což v podstatě absolutně řeší můj problém :) Vědět to dřív, tak tady neotravuju..
Nicméně stejně děkuji za pomoc, zkoušel jsem i dle tvého návodu a alespoň jsem se zase něco nového naučil.