Komponenta uvnitř dynamicky vkládaného textu
- David Růžička
- Člen | 43
Měl by někdo nějaký nápad, jak by se v nette dal vyřešit následující problém?: Generuji stránku s článkem. V textu článku mohou být porůznu vložené značky, na jejichž místo by se při vykreslování vložila nějaká vykreslitelná componenta/control (například značka {gallery 15} pro vykreslení obrázkové galerie s id=15). Lze to za pomoci nette nějak rozumně udělat? V textu článku navíc mohou být vloženy značky stejného typu vícekrát (např dvě galerie s různým nebo i stejným id)
- Foowie
- Člen | 269
Podívej se jak funguje a co generuje makro {control xyz}
Následně bych postupoval takto:
- Získal bych text z databáze
- Vyescapoval bych ho
- Nahradil bych značky za php kód na vykreslení komponent
- David Růžička
- Člen | 43
Díky, ale bohužel pořád tápu. Zkoumal jsem kód nette a došel jsem k tomu, že bych asi měl volat $parser->expandMacroexpandMacro(‚widget‘, ‚jmeno_controlu‘). Což by mi snad mělo vyhodit vygenerovaný kód prvku. Nepodařilo se mi ale zjistit, kde získám parser. Zkoušel jsem v presenteru přepsat metodu templatePrepareFilters, ve které se vytváří a registruje Engine přes $template->registerFilter(), ale z nějakého důvodu se nikdy nezavolá.
- Vojtěch Dobeš
- Gold Partner | 1316
Nešlo by použít , respektive teď
už obyčejnou Nette\Templating\Template?
Tedy vytvořit si ji, předat jí získaný text z databáze a následně tuto
šablonu předat jako proměnnou do standardní šablony toho kterého viewů,
ve kterém se to provádí. A tam ji prostě vypsat. Jediné co je třeba je
té nové Template znovu zaregistrovat potřebné filtry, helpery a předat
potřebné proměnné (viz Nette\Application\UI\Control::createTemplate().StringTemplate
Jo, a samozřejmě ty zvláštní značky: přidání vlastního makra.
- Foowie
- Člen | 269
Nástin:
preg_replace_callback(
"/{gallery [0-9]+}/",
function($match) {
$id = ziskej nejak z $match id;
$control = $this->getWidget("gallery");
if ($control instanceof Nette\Application\UI\IPartiallyRenderable)
$control->validateControl();
return $control->render($id);
},
$string
);
Edit: Uvědomil jsem si, že $control->render()
nevrací ale
přímo vykresluje, takže výstup musíš zachytit a vrátit (pomocí ob_start,
…) ;)
Editoval Foowie (23. 6. 2011 20:03)
- Filip Procházka
- Moderator | 4668
Složitěji by to nešlo? Co to udělat trošku univerzálně a třeba
použít StringTemplate
na ten výstup s vlastním macrem? Mám
pocit že i obyčejný template by to měl nyní zvládnout, pomocí
setSource
.
Mimochodem to řešení je nic moc, nejlepší by bylo udělat si modul do Texy!.
Editoval HosipLan (24. 6. 2011 7:54)
- Vojtěch Dobeš
- Gold Partner | 1316
Dovolím si také nástin :).
Kód v presenteru (třeba nějaká metoda
render<Something>
):
use Nette\Latte;
use Nette\Templating\Template;
$latte = new Latte\Engine;
$template = new Template;
$template->source = $article->content; // content obsahuje vpodstatě Latte šablonu
$template->registerFilter($latte);
Šablona již rozumí latte
, další řádek zprovozní makra
control
a link
, resp. n:href
(možná by
to ještě chtělo zprovoznit helpery, přidat svoje další makra, viz
příspěvek výše). A následně šablonu šupnem do „hlavní“ šablony,
kterou používá presenter.
$template->presenter = $template->control = $this;
$this->template->articleContent = $template;
A v šabloně:
{!$articleContent}
Editoval vojtech.dobes (23. 6. 2011 20:26)
- David Růžička
- Člen | 43
Díky všem za příspěvky. Použil jsem Vojtěchovu variantu, jenom jsem použil StringTemplate:
use Nette\Latte;
use Nette\Templating\StringTemplate;
$latte = new Latte\Engine;
$template = new StringTemplate();
$template->content = "{widget gallery 10}"; // content obsahuje vpodstatě Latte šablonu
$template->registerFilter($latte);
$template->presenter = $template->control = $this;
$this->template->myVar = $template;
- Bernard Williams
- Člen | 207
Nazdárek,
může mi někdo poradit, proč mi to nejde? Mám to úplně stejně jako v postech výš a nic se nevygeneruje:
$text = 'Nejaky muj text
{control example}
konec meho textu';
$latte = new LatteFilter;
$template = new StringTemplate();
$template->content = $text;
$template->registerFilter($latte);
$template->presenter = $template->control = $this;
$this->template->text = $template;
Zkoušel jsem to i s pouhým Template(), ale bez výsledku. Není potřeba zavolat __toString()? Nebo se to volá automaticky v šabloně při {!$text}? V šabloně se navíc vůbec nezobrazí jakýkoliv text – ani s ani bez dané komponenty.
Vyvíjím na PHP 5.3 (na serveru je 5.2) a bez jmenných prostorů. Nette 2.0-beta, d2c39f5 released on 2011–07–02.
Budu rád za jakoukoliv radu. Už nad tím sedím několik hodin.
Bernard
- David Růžička
- Člen | 43
Mně funguje tohle:
$latte = new Latte\Engine;
$template = new StringTemplate();
$template->content = "xx {widget neco} xx";
$template->registerFilter($latte);
$template->presenter = $template->control = $this;
$this->template->myVar = $template;
- Bernard Williams
- Člen | 207
Tak jsem to zkusil i se jmennými prostory a stejný výsledek. Jakou verzi Nette používáš? Podle „widget“ bych řekl, že ještě nějakou starou, ne?
Chyba bude nejspíš ve StringTemplate() ve spojení s Nette 2 beta. Funguje někomu správně v nové verzi?
- hAssassin
- Člen | 293
@Bernard Williams > ano, StringTemplate v nove verzi nefunguje a potreba ho upravit. Staci vsak trochu hledat zde na foru a funkcni(!) reseni je v tomto vlakne.
Editoval hAssassin (31. 8. 2011 19:01)
- Filip Procházka
- Moderator | 4668
Doplnil bych šikovnější variantu, kde není potřeba nic nastavovat, protože to udělá výchozí továrnička v komponentě.
// v presenter nebo controlu
$template = $this->createTemplate('Nette\Templating\Template');
$template->setSource($tvojeLatteStringSablona);
$template->render();
- Bernard Williams
- Člen | 207
@hAssassin: O tom vlákně jsem věděl a taky jsem ho použil.. bohužel jsem jeden řádek přehlédl, a proto mi to nejelo.. Tolik hodil v pr.. pro takovou blbost :-/