How to generate links in templates
- simPod
- Member | 383
I have the same issue as the guy here https://forum.nette.org/…y-componenty#…
I followed the thread, docs and https://phpfashion.com/…lech-a-nette
I don't want any magic so I went with LatteEngine
which is the
least magical (it has this
though Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());
meh)
and I'm getting
Undefined property: stdClass::$uiControl
This is generated when renderToString()
is called:
echo LR\Filters::escapeHtmlText($this->global->uiControl->link(...
There's no uiControl
registered on global though.
I expected
\Nette\Bridges\ApplicationLatte\LatteFactory::create()
to give me
fully working latte renderer.
So I noticed there's TemplateFactory
that requires
UI\Control
instance and internally setups LatteEngine properly.
I've created this abomination that can be used only from Control (presenters etc.).
public function create(Control $control): Engine
{
$template = $this->templateFactory->createTemplate($control);
$reflectionClass = $template instanceof DefaultTemplate
? (new ReflectionClass($template))->getParentClass()
: new ReflectionClass($template);
$latteProperty = $reflectionClass->getProperty('latte');
$latteProperty->setAccessible(true);
return $latteProperty->getValue($template);
}
I can't use Template because it cannot be rendered to string. Is there's a way to render latte properly using OOP?
- simPod
- Member | 383
@MarekBartoš helped me with his snippet. This is what I've ended up with and that's enough for the current project. Thanks!
public function create(Control $control): Engine
{
$template = $this->templateFactory->createTemplate($control);
return $template->getLatte();
}
Last edited by simPod (2021-07-31 13:28)
- Rick Strafy
- Nette Blogger | 81
Hi, try this, use Nette\Bridges\ApplicationLatte\LatteFactory
and Nette\Application\LinkGenerator
from DI and then
$latte = $this->latteFactory->create();
UIMacros::install($latte->getCompiler());
$latte->addProvider('uiControl', $this->linkGenerator);
and you can use that to render templates to string, for instance
$emailTemplate = new EmailTemplate($latte);
$emailTemplate->something = 'test';
$emailTemplate->renderToString();
It can be used outside of controls/presenters.
EmailTemplate extends Nette\Bridges\ApplicationLatte\Template
, that
way you can have strict typed templates
Last edited by Rick Strafy (2021-07-31 14:59)
- Marek Bartoš
- Nette Blogger | 1263
I would go with something like this to not loose functionality of TemplateFactory, most importantly all the macros and filters from outside of Nette
use Nette\Application\LinkGenerator;
use Nette\Bridges\ApplicationLatte\Template;
use Nette\Bridges\ApplicationLatte\TemplateFactory;
class FooTemplate extends Template
{
public string $foo;
}
class TemplateCreator
{
public function __construct(
private TemplateFactory $templateFactory,
private LinkGenerator $linkGenerator,
)
{
}
/**
* @template T of Template
* @param class-string<T> $templateClass
* @return T
*/
public function createTemplate(string $templateClass): Template
{
$template = $this->templateFactory->createTemplate(class: $templateClass);
assert($template instanceof $templateClass);
$latte = $template->getLatte();
$latte->addProvider('uiControl', $this->linkGenerator);
return $template;
}
}
$creator = new TemplateCreator();
$template = $creator->createTemplate(FooTemplate::class);
$template->foo = 'bar';
$template->renderToString(__DIR__ . '/path/to/email.latte');
Last edited by Marek Bartoš (2021-07-31 13:56)