Rozhodnutí o vykreslení componenty popř předání šabloně
- Danny
- Člen | 146
Dobrý den,
řeším situaci kdy na základě parametru chci vykreslit 1 z 3 možností
do šablony text/komponentu(formulář)/komponentu na přihlášení. Nechci to
řešit v šabloně stylem {if $param != $id_uziv} ale rád bych to řešil
v presenteru přijde mi to čistější. Chtěl bych vytvořit nějakou
actionDetail v které bych provedl dotazy a na základě toho vykreslil tu
komponentu, nebo šabloně předal určitý layout který se má vykreslit do
ní ale nejsem si jistý jak na to.
Něco jako
public function actionDetail($id = null)
{
if($this->id == this->user->getIdentity()->username){
/* ... includovat komponentu */
}
elseif (condition) {
/* ... */
$this->setView('renderDenied');
}
else{
/* ... */
}
}
public function renderDenied()
{
/* ...hláška */
}
/* .....atd */
Mohl by mi prosím někdo poradit?
Děkuji za jakoukoliv radu :)
- Danny
- Člen | 146
Díky :) já bych spíše potřeboval vědět jak to využít ve spolupráci s latte šablonou, protože moc nerozumim jak se v šabloně rozhodne co se tedy vykreslí pokud budu mít v presenteru na to nějakou menší logiku. Ono se to teda spíše rozhodně v presenteru a šabloně jenom předá. Nechci na to vytvářet celou komponentu protože to použiju pravděpodobně jenom jednou takže bych to rád řešil přes ten actionDefault a rozhodnout v něm jaka .latte šablona se případně předá, nechci je odkazovat na /show/ /notfound/ nebo /denied/ potřebuju to vykreslit na jedné stránce a změnit kus HTML stránky. Mohl by si mi hodit nějakej tip jak na to? :)
class ProfilePresenter
{
function actionShow($username)
{
if ($username != $user->username) {
$this->view = 'notfound';
} elseif (!$user->isLoggedIn()) {
$this->view = 'denied';
} else {
$this->view = 'show';
}
}
function renderShow()
{ ... }
function renderNotfound()
{ ... }
function renderDenied()
{ ... }
}
S tím že v šablonách už bych měl konkrétní řešení jako třeba {control form} apod. Jestli by tohle řešení teda vůbec šlo.
Děkuju :)
Editoval Danny (2. 9. 2016 14:12)
- Pavel Kravčík
- Člen | 1196
Moc nerozumím konkrétnímu zadání. Ale já používám třeba tohle a přijde mi to hezké.
// Komponenta
class UserBoxComponent extends UI\Control
{
// constructor pro všechny tři případy stejný
public function renderLogin()
{
$this->template->setView('userNotLogged.latte');
}
public function renderLogged()
{
$this->template->setView('userIsLogged.latte');
}
public function renderAdmin()
{
$this->template->setView('userIsAdmin.latte');
}
}
//Pak si presenteru udělej ty svoje podmínky a v těch latte vykreslíš konkrétní stav komponenty takhle:
{control userBox:admin}
{control userBox:login}
{control userBox:logged}
- artemevsin
- Člen | 61
pak je ještě možnost nastavovat nějaké hodnoty a před vykreslením komponenty je v komponentě nastavit:
<?php
class MyPresenter {
private $parameter;
public function actionSomeAction()
{
$this->parameter = 'nejaky rozhodujici parameter';
}
protected function createComponentMyComponent()
{
return $this->componentFactory->create($this->parameter);
//nebo
$component = $this->componentFactory->create();
$component->setParameter($this->parameter);
return $component;
}
}
?>
když se v šabloně narazí na {control myComponent}, tak se zavolá metoda createComponentMyComponent a vrátí ti už nastavenou komponentu.
To co se má vykreslit, popř. které .latte se má použit, se rozhodne uvnitř komponenty.
<?php
class MyComponent {
private $parameter;
public function __construct($parameter)
{
$this->parameter = $parameter;
}
public function render()
{
switch($this->parameter) {
case 'login':
$this->template->setFile('login.latte');
break;
case 'error':
$this->template->setFile('error.latte');
break;
}
}
}
?>
takže rozhodnutí, co se má vykreslit, je na komponentě a ne na šabloně. pokud to chceš mít flexibilnější, tak je lepši použit to co navrhuje @PavelKravčík, ale to ty asi nechceš, protože pak budeš muset v šabloně použit
{if $neco} {control myComponent:neco} {else} {control myComponent:necoJineho} {/if}
- Danny
- Člen | 146
Super ! :) přesně to jsem potřeboval děkuju moc už mi to funguje. Akorát se mi nějak nedaří injectnout authenticator, dal jsem si do té komponenty komponentu na přihlášení kterou jsem měl předtím v BasePresenteru.
<?php
use Nette\Application\UI\Form,
Nette\Security\User;
class BoxComponent extends UI\Control
{
private $parameter;
private $user;
private $authenticator;
public function __construct($parameter,User $user, Authenticator $authenticator)
{
$this->parameter = $parameter;
$this->user = $user;
$this->authenticator = $authenticator;
}
public function loginFormSucceeded($form)
{
try{
$values = $form->getValues();
$user = $this->user;
if ($values->login_time) {
$this->user->setExpiration('14 days', TRUE);
} else {
$this->user->setExpiration('120 minutes', TRUE);
}
$user->setAuthenticator($this->authenticator);
$user->login($values->email,$values->password);
$this->redirect('Homepage:default');
} catch (Nette\Security\AuthenticationException $e) {
$this->FlashMessage($e->getMessage(),'danger');
$this->redirect('Sign:in');
}
}
}
services:
- BoxComponent($parameter)
router: App\RouterFactory::createRouter
authenticator: Authenticator
- artemevsin
- Člen | 61
Authenticator se ti nepředává kvůli tomu, že v definici služby ho neuvádíš, máš tam jen $parameter.
Musel bys to v config.neon definovat takto (zhruba):
<?php
services:
- BoxComponent($parameter, @security.user, @authenticator)
?>
Ale není to tak dlouho, co mi @DavidMatějka radil, že komponenty není dobré registrovat jako služby a vždy je lepši si vytvořit továrničku a tu teprve zaregistrovat jako službu. Továrnička se pak postará o předání všech potřebných závislosti.
<?php
interface IBoxComponentFactory {
/**
* @param string $parameter
* @return BoxComponent
*/
public function create($parameter);
}
?>
<?php
services:
- IBoxComponentFactory
?>