Rozhodnutí o vykreslení componenty popř předání šabloně

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Danny
Člen | 146
+
0
-

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 :)

CZechBoY
Člen | 3608
+
0
-

Komponentu pripojis takhle

$komponenta = new Komponenta;
$this->addComponent($komponenta, 'jmeno');
Danny
Člen | 146
+
0
-

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
+
+2
-

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
+
+1
-

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
+
0
-

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
+
+2
-

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
?>