Jak vypsat stejný vzor hodnot ve více šablonách

ForestCZE
Člen | 209
+
0
-

Ahoj, prosím o pomoc. Vytáhnu si uživatele:

Ve třídě UserManager

public function getInfo(string $username)
{
	return $this->database->getUsers()->where('username = ?', $username)->fetch();
}

V presenteru bych to měl pak předat do templaty:

$this->template->info = $this->userManager->getInfo('Forest');

Latte:

<table>
	<tr><td>Jméno</td> <td></td>{$info->firstname}</tr>
	<tr><td>Příjmení</td> <td></td>{$info->lastname}</tr>
	<tr><td>Věk</td> <td></td>{$info->age}</tr>
</table>

A tento vzor budu mít pokaždé, akorát že na jedné stránce si ty data vytáhnu podle přihlášeného uživatele a jinde třeba zase podle hledaného uživatele ve formuláři.

Jak to udělat tak, abych to nemusel posílat do templaty v každém presenteru zvlášť a nemusel jsem tu tabulku vkládat do každého latte souboru zvlášť? Nějak to předat, abych mohl mít třeba:

userinfo.latte

{define userinfo}
	<table>
		<tr><td>Jméno</td> <td></td>{$info->firstname}</tr>
		<tr><td>Příjmení</td> <td></td>{$info->lastname}</tr>
		<tr><td>Věk</td> <td></td>{$info->age}</tr>
	</table>
{/define}

A v těch šablonách, kde to chci vypsat:

{import 'userinfo.latte'}
{innclude userinfo}

Díky předem za rady :)

Editoval ForestCZE (14. 5. 2019 19:01)

MajklNajt
Člen | 471
+
+1
-

spraviť komponentu?

ForestCZE
Člen | 209
+
0
-

MajklNajt napsal(a):

spraviť komponentu?

Kromě formuláře jsem komponenty ještě nepoužil. Takže smím tě poprosit o ukázku? Děkuji.

ForestCZE
Člen | 209
+
0
-

Tak jsem se o něco pokusil:

UserInfoControl.php

<?php

namespace App\FrontModule\Components\UserInfo;

use Nette\Application\UI\Control;

final class UserInfoControl extends Control
{
    public function render()
    {
        $this->template->setTemplate(__DIR__ . '/userinfo.latte');
        $this->template->render();
    }
}

UserPresenter

protected function createComponentUserInfo()
{
	$control = new UserInfoControl;
	return $control;
}

Tam, kde to potřebuji:

{control userInfo}

Vyhazuje mi to: Invoking filters on Template object is deprecated, use getLatte()->invokeFilter().

EDIT: Už vím. Tu render metodu je potřeba upravit takto:

$template = $this->getTemplate();
$template->setFile(__DIR__ . '/userinfo.latte');
$template->render();

Editoval ForestCZE (14. 5. 2019 20:54)

MajklNajt
Člen | 471
+
+4
-

@ForestCZE tej komponente určite budeš chcieť cez konštruktor predať nejaké závislosti, takže si vytvor na ňu továrničku (stačí interface)

interface IUserInfoControlFactory
{
    /** @return App\FrontModule\Components\UserInfo\UserInfoControl */
    public function create(): App\FrontModule\Components\UserInfo\UserInfoControl;
}

továrničku zaregistruj v config.neon ako službu

services:
	- App\FrontModule\Components\UserInfo\IUserInfoControlFactory

a presenter bude potom vyzerať takto:

/** @var App\FrontModule\Components\UserInfo\IUserInfoControlFactory @inject */
public $userInfoControlFactory;

protected function createComponentUserInfo(): App\FrontModule\Components\UserInfo\UserInfoControl
{
    return $this->userInfoControlFactory->create();
}
ForestCZE
Člen | 209
+
0
-

MajklNajt napsal(a):

@ForestCZE tej komponente určite budeš chcieť cez konštruktor predať nejaké závislosti, takže si vytvor na ňu továrničku (stačí interface)

interface IUserInfoControlFactory
{
    /** @return App\FrontModule\Components\UserInfo\UserInfoControl */
    public function create(): App\FrontModule\Components\UserInfo\UserInfoControl;
}

továrničku zaregistruj v config.neon ako službu

services:
	- App\FrontModule\Components\UserInfo\IUserInfoControlFactory

a presenter bude potom vyzerať takto:

/** @var App\FrontModule\Components\UserInfo\IUserInfoControlFactory @inject */
public $userInfoControlFactory;

protected function createComponentUserInfo(): App\FrontModule\Components\UserInfo\UserInfoControl
{
    return $this->userInfoControlFactory->create();
}

Funguje to suprově. Mám teda:

protected function createComponentUserInfo() : UserInfoControl
{
	return $this->userInfoControlFactory->create($this->user->getIdentity()->username);
}

Mohu tuto komponentu nějak vytvořit až po zpracování formuláře?

Když mám:

public function searchUserSucceeded(Form $form)
{
	$values = $form->getValues();
	//zde vytvořit komponentu a do argumentu fce "create" dosadit hodnotu z formuláře
}

Jak na to? Díky :)

MajklNajt
Člen | 471
+
0
-

@ForestCZE dynamicky môžeš dosadiť premennú cez multiplier:

protected function createComponentUserInfo() : UserInfoControl
{
	return new Nette\Application\UI\Multiplier(function($username) {
		return $this->userInfoControlFactory->create($username);
	});
}

public function renderShowUserInfo()
{
	$this->template->username = $this->user->getIdentity()->username;
}

v šablóne potom

{control userInfo-$username}

Ale nepchaj tú premennú do šablóny hneď po odoslaní formulára! Po úspešnom spracovaní formulára by mal nasledovať redirect – viď napr. https://en.wikipedia.org/…Redirect/Get

EDIT: komponenta sa vytvára až keď ju potrebuješ – v tomto prípade použitím makra {control ...}, takže ak jej vytvorenie chceš podmieniť, môžeš napr. takto:

{ifset $username}
{control userInfo-$username}
{/ifset}

Editoval MajklNajt (15. 5. 2019 9:27)

ForestCZE
Člen | 209
+
0
-

MajklNajt napsal(a):

@ForestCZE dynamicky môžeš dosadiť premennú cez multiplier:

protected function createComponentUserInfo() : UserInfoControl
{
	return new Nette\Application\UI\Multiplier(function($username) {
		return $this->userInfoControlFactory->create($username);
	});
}

public function renderShowUserInfo()
{
	$this->template->username = $this->user->getIdentity()->username;
}

v šablóne potom

{control userInfo-$username}

Ale nepchaj tú premennú do šablóny hneď po odoslaní formulára! Po úspešnom spracovaní formulára by mal nasledovať redirect – viď napr. https://en.wikipedia.org/…Redirect/Get

EDIT: komponenta sa vytvára až keď ju potrebuješ – v tomto prípade použitím makra {control ...}, takže ak jej vytvorenie chceš podmieniť, môžeš napr. takto:

{ifset $username}
{control userInfo-$username}
{/ifset}

Asi jsme se špatně pochopili. Mám formulář (jedno textové pole), kde vyhledávám uživatele:

protected function createComponentSearchUser()
    {
        $form = new Form;
        $form->addText('username', 'Uživatelské jméno:')
             ->setRequired('Zadej uživatelské jméno.')
             ->setAttribute('placeholder', 'Uživatelské jméno')
             ->setAttribute('autocomplete', 'off')
             ->setAttribute('spellcheck', 'false');

        $form->addSubmit('search', 'Hledat');

        $form->addProtection('Vypršel časový limit.');
        $form->setMethod('GET');
        $form->onSuccess[] = [$this, 'searchUserSucceeded'];
        return $form;
    }

    public function searchUserSucceeded(Form $form)
    {
        $values = $form->getValues();
		$exists = $this->database->getUsers()->where('username = ?', $values['username'])->fetch();
		if($exists)
			....->create($values['username']); //zde potřebuji předat argument a vytvořit komponentu
    }
MajklNajt
Člen | 471
+
0
-

@ForestCZE v tom prípade by to malo fungovať tak, ako som písal – pomocou Multiplieru a nasetovania do templaty v searchUserSucceeded

public function searchUserSucceeded(Form $form)
{
    $values = $form->getValues();
    $exists = $this->database->getUsers()->where('username = ?', $values['username'])->fetch();
    if($exists) $this->template->username = $values['username'];
}
{ifset $username}
{control userInfo-$username}
{/ifset}
ForestCZE
Člen | 209
+
0
-

MajklNajt napsal(a):

@ForestCZE v tom prípade by to malo fungovať tak, ako som písal – pomocou Multiplieru a nasetovania do templaty v searchUserSucceeded

public function searchUserSucceeded(Form $form)
{
    $values = $form->getValues();
    $exists = $this->database->getUsers()->where('username = ?', $values['username'])->fetch();
    if($exists) $this->template->username = $values['username'];
}
{ifset $username}
{control userInfo-$username}
{/ifset}
protected function createComponentUserInfo() : UserInfoControl
    {
        return new Multiplier(function($username){
            return $this->userInfoControlFactory->create($username);
        });
    }

Return value of App\FrontModule\Presenters\ContactsPresenter::createComponentUserInfo() must be an instance of App\Components\UserInfo\UserInfoControl, instance of Nette\Application\UI\Multiplier returned

Chápu, co to znamená, ale nevím, jak to vyřešit. Předem děkuji za pomoc a za trpělivost.

David Matějka
Moderator | 6445
+
+2
-

multiplier neslouzi k takovemu predavani hodnot do komponent.

v tom searchUserSucceeded proved redirect a to username si uloz do parametru:

$this->redirect('this', ['username' => $values['username']]);

pote v createComponentUserInfo budes mit

protected function createComponentUserInfo() : UserInfoControl
    {
        return $this->userInfoControlFactory->create($this->getParameter('username'));
    }
ForestCZE
Člen | 209
+
0
-

David Matějka napsal(a):

multiplier neslouzi k takovemu predavani hodnot do komponent.

v tom searchUserSucceeded proved redirect a to username si uloz do parametru:

$this->redirect('this', ['username' => $values['username']]);

pote v createComponentUserInfo budes mit

protected function createComponentUserInfo() : UserInfoControl
    {
        return $this->userInfoControlFactory->create($this->getParameter('username'));
    }
protected function createComponentUserInfo() : UserInfoControl
{
	return $this->userInfoControlFactory->create($this->getParameter('username'));
}

$user_exists = $this->database->getUsers()->where('username = ?', $values['username'])->fetch();
if($user_exists)
{
	$this->redirect('this', ['username' => $values['username']]);
	$this->template->searched = true;
}

{ifset $searched}
	{control userInfo}
{/ifset}

Netuším, co dělám špatně, ale komponenta se nevykreslí.

EDIT: To přesměrování jsem dal pryč a už to funguje. Ono asi není potřeba, protože metoda GET se o to postará.

Editoval ForestCZE (15. 5. 2019 14:28)

Gavrilo
Člen | 46
+
0
-

ForestCZE napsal(a):

David Matějka napsal(a):

multiplier neslouzi k takovemu predavani hodnot do komponent.

v tom searchUserSucceeded proved redirect a to username si uloz do parametru:

$this->redirect('this', ['username' => $values['username']]);

pote v createComponentUserInfo budes mit

protected function createComponentUserInfo() : UserInfoControl
    {
        return $this->userInfoControlFactory->create($this->getParameter('username'));
    }
protected function createComponentUserInfo() : UserInfoControl
{
	return $this->userInfoControlFactory->create($this->getParameter('username'));
}

$user_exists = $this->database->getUsers()->where('username = ?', $values['username'])->fetch();
if($user_exists)
{
	$this->redirect('this', ['username' => $values['username']]);
	$this->template->searched = true;
}

{ifset $searched}
	{control userInfo}
{/ifset}

Netuším, co dělám špatně, ale komponenta se nevykreslí.

EDIT: To přesměrování jsem dal pryč a už to funguje. Ono asi není potřeba, protože metoda GET se o to postará.

Pošli celý kód a nie len jeho časť. Pravdepodobne tam vidím chybu.

ForestCZE
Člen | 209
+
0
-

Tak vyřešeno :) Děkuji mockrát @MajklNajt & @DavidMatějka za pomoc :)

MajklNajt
Člen | 471
+
0
-

@DavidMatějka prečo podľa teba neslúži multiplier na predávanie takejto hodnoty do komponenty? zadanie znelo „tento vzor budu mít pokaždé, akorát že na jedné stránce si ty data vytáhnu podle přihlášeného uživatele a jinde třeba zase podle hledaného uživatele ve formuláři.“, čiže je veľká pravdepodobnosť, že tá komponenta sa vyskytne na stránke aj viackrát, kedy bude multiplier nezbytný… toto je podľa mňa ukážkové použitie multiplieru

ForestCZE
Člen | 209
+
0
-

MajklNajt napsal(a):

@DavidMatějka prečo podľa teba neslúži multiplier na predávanie takejto hodnoty do komponenty? zadanie znelo „tento vzor budu mít pokaždé, akorát že na jedné stránce si ty data vytáhnu podle přihlášeného uživatele a jinde třeba zase podle hledaného uživatele ve formuláři.“, čiže je veľká pravdepodobnosť, že tá komponenta sa vyskytne na stránke aj viackrát, kedy bude multiplier nezbytný… toto je podľa mňa ukážkové použitie multiplieru

Vyskytne se pouze jednou na jedné stránce, podruhé úplně na jiné stránce (v jiném presenteru a šabloně).

David Matějka
Moderator | 6445
+
+1
-

@MajklNajt tak udelas dve komponenty. navic jako hodnotu tam muzes predat jen [a-z0-9]+

multiplier je primarne urceny v situaci, kdy komponenty vypisujes pres foreach