Opakovanie kodu – pomoc s komponentou
- juraj0137
- Člen | 1
Ahojte, pokusim sa vam nacrtnut moj problem.
V roznych templateoch (na homepage, pri vyhladavani, pri prezerani urcitej
kategorie) sa mi stale opakuje kus kodu.
Zjednodusena forma:
{foreach $books as $book}
<img src="/image/{$book->id}">
<h2>{$book->title}</h2>
<p>{$book->description}</p>
{/foreach}
V presentery
public function renderDefault(){
..
// zapis je iba symbolicky, v kazdom presentery su rozne podmienky pre vyber knih
$this->template->books = $this->db->find($by);
..
}
funguje mi to dobre, len pri uprave sablony musim nasledne upravovat ten isty
kod aj v ostatnych sablonach .. predpokladam ze by sa to dalo riesit cez
komponenty, cize by napr. pri vyhladavani vytvorilo tolko komponent kolko by
bolo vysledkov vyhladavania, a tie by sa vypisali potom na stranku .. teoreticky
v hlave mi to ide, ale nemozem to dostat do fungujuceho kodu .. potreboval by
som vediet ako by mala vyzerat komponenta, ako upravit presenter v ktorom to
vypisujem a aj sablonu.
Dufam ze som to popisal ako-tak zrozumitelne. Viem ze je tu ohladom komponent
vela tem, ale po prestudovani par z nich sa mi to stale nedari.
- thm
- Člen | 147
Zdar, jsem sice také začátečník, ale pokusím se ti to vysvětlit. Opravte mě někdo, jestli šířím bludy.
Komponenta:
class BookList extends Nette\Application\UI\Control{
/** @var Nette\Database\Connection */
private $connetion;
/** @var Array */
private $findBy;
public function __construct(Nette\Database\Connection $connetion) {
$this->connetion= $connetion;
}
public function setFindBy($findBy){
$this->findBy = $findBy;
}
public function render(){
$this->template->setFile(__DIR__ . '/bookList.latte');
$books= $this->connection->table('books');
if($this->findBy) $books->where($this->findBy);
$this->template->books= $books;
$this->template->render();
}
}
Komponenta má kontruktor, tam posílám Connection, protože ho potřebuje
využívat.
Komponenta má metodu render(), ve které nastavíme soubor se šablonou a do
ní pak pošleme nějakou proměnnou, nakonec vyrenderujeme.
Komponentě jsem udělal metodu na oříznutí výsledků z databáze.
(komponentu lze udělat i lépe, ale pro názornost stačí)
Šablonu máš hotovou.
Nyní někde v presenteru (podle toho kde všude jí chceš zobrazovat, tak použij nadřazenější presenter) napíšeme továrničku na tuto komponentu. Ta má předepsaný název createComponent<NazevKomponenty>() a bude vracet instanci komponenty.
public function createComponentBookList(){
return new BookList($this->connection);
}
Komponenta hotova, vytvoří se až když je potřeba. Někdy je to až v šabloně. Když Nette při renderování narazí na makro
{control bookList}
jukne jestli už tuto komponentu má připojenou k presenteru, pokud ne, zavolá metodu createComponent<NazevKomponenty>() a vyrenderuje.
Někdy je ale potřeba komponentu doladit než se vyrenderuje a to je i náš případ. Někde v presenteru je potřeba filtrovat výsledky. Komponentu můžeme v presenteru zavolat tímto:
$this['bookList']->setFindBy(array('author' => 'Grundl'));
Když se narazí v presenteru na tuto řádku a komponenta neexistuje, Nette zavolá createComponent<NazevKomponenty>() a vyrobí ji. Pak už máme odkaz na instanci komponenty. Když dojde na {control bookList}, tak ji jenom vyredneruje (už ji má vytvořenou).
Snad ti to trochu pomůže.
- Šaman
- Člen | 2666
V tomhle případě, protože parametr je potřeba jen k vykreslení, je možné předat parametr až render metodě.
<?php
public function render($findBy = NULL){
$this->template->setFile(__DIR__ . '/bookList.latte');
$books= $this->connection->table('books');
if(isset($findBy)) $books->where($findBy);
$this->template->books= $books;
$this->template->render();
}
?>
Seznam všech knih:
{control bookList}
Seznam knih od Davida:
{control bookList, 'author' => 'Grudl'}
Je to stále stejná komponenta, pokaždé jinak nastavené vykreslování.
Pravá komponenta mívá i vnitřní stavy (pak se ale musí nastavit už
v továrničče, parametr render metody nestačí). A u takové komponenty
s vnitřními stavy se samozřejmě používá vždy nová instance, tady je to
ale zbytečné.
Když si ji dáš její továrničku do BasePresenteru (není to ideální
z pohledu čistoty, ale ušetří to psaní), tak tu komponentu budeš moci
používat ve všech šablonách presenterů.
// Edit: upravil jsem pár překlepů v kódu a Davidovo příjmení. :)
Editoval Šaman (18. 3. 2014 22:53)