Vytvorenie vlastnej funkcie pre latte
- vladimir.biro
- Člen | 163
Ahojte.
Prosim vas, je mozne spravit nieco take, ze do <div> <a> .. cohokolvek pridam napriklad n:hidden a tento prvok sa mi potom nebude generovat a teda zobrazovat na vystupe?
Ide mi o to, ze mam v systeme nieco ako moduly (pozor, nemyslit si s Nette modulmi) a na zaklade prihlasenia uzivatela model vyhodnoti ktore moduly ma mat uzivatel pristupne.
Moduly, ktore su pre uzivatela pristupne za zapisu do pola.
Pr:
$bundles = [1,2,5,78,99];
V kode mam napriklad button, ktory patri modulu č.4 a teda by bolo riesenie spravit:
<div n:if="inArray(4, $bundles)"> ... </div>
No chcel by som si to nejako zjednodusit a to tym, ze by som si vytvoril filter a zapisoval:
<div {4:bundle}> ... </div>
tento filter by mal na vystupe bud nic, vtedy by sa <div> normalne zobrazil, alebo n:hidden
Potialto by som to zvladol, no potreboval by som v tomto pripade dany div nezobrazovat a to ani v kode, cize ziadne schovavanie stylom a ani javascriptom.
Snad som to vysvetlil dostatocne.
Dakujem za pripadne rady a info :)
- vladimir.biro
- Člen | 163
ali napsal(a):
Ja bych rek, ze n:if je ta spravna cesta.
A sla by aspon spravit vlastna funkcia?
Napriklad:
<a href="#" n:if="b(4)"></a>
S tym, ze by som si niekde vytvoril:
<?php
b($i) {
return (in_array($i, $this->bundleManager->getBundles())) ? true : false;
}
...
// -- toto by samozrejme bralo data z DB a po roznych kontrolach
getBundles()
{
return [1,2,3,4];
}
?>
Ide mi o to, co najviac to zjednodusit, pretoze to budem pouzivat kade tade a zaroven aby som do tej funkcie vede zasahovat aj neskor a zaroven nemusel vsetko prepisovat na x miestach.
Editoval vladimir.biro (23. 11. 2017 19:59)
- ali
- Člen | 342
Jdes na to blbe, snazis se vracet z sablony do presenteru, coz je spatne.
Udelej to tak, ze $this->bundleManager->getBundles() ti bude vracet pole/object, ktery predas do sablony, neco jako:
$this->template->bundles = [
1 => ['bundleId' => 1, 'name' => 'foo1', 'havePermission' => true],
2 => ['bundleId' => 2, 'name' => 'foo2', 'havePermission' => false],
...
];
A v sablone to pak budes vykreslovat nejakym takovymhle stylem:
{foreach $bundles as $bundle}
{if $bundle[havePermission]}
<a>{$bundle[name]}</a>
{else}
<i>{$bundle[name]}</i>
{/if}
{/foreach}
Editoval ali (24. 11. 2017 5:46)
- vladimir.biro
- Člen | 163
ali napsal(a):
Jdes na to blbe, snazis se vracet z sablony do presenteru, coz je spatne.
Udelej to tak, ze $this->bundleManager->getBundles() ti bude vracet pole/object, ktery predas do sablony, neco jako:
$this->template->bundles = [ 1 => ['bundleId' => 1, 'name' => 'foo1', 'havePermission' => true], 2 => ['bundleId' => 2, 'name' => 'foo2', 'havePermission' => false], ... ];
A v sablone to pak budes vykreslovat nejakym takovymhle stylem:
{foreach $bundles as $bundle} {if $bundle[havePermission]} <a>{$bundle[name]}</a> {else} <i>{$bundle[name]}</i> {/if} {/foreach}
fuu .. to som prave nechcel.
Chcel som, aby som to mal v sablone co najjednoduchsie. Tvoje riesenie je este komplikovanejsie (pre oko), ako to, co som popisal vyssie.
Samozrejme ked sa jedna o automaticky vypis menu (napriklad) tak to je samozrejem OK. Menu dokonca velmi podobne generujem, no potrebujem kontrolovat aj rozne casti kodu vsade na stranke a taketo podminekovanie by mi z toho spravilo bodrel.
V kazdom priprade ale dakujem za snahu :)
- vladimir.biro
- Člen | 163
Tak som to nakoniec vyriesil cekom elegantne cez makra … akurat som sa ich musel naucit vytvarat :D
Riesenie:
1. V modeli si spravim funkciu na vygenerovanie zoznamu ID-ciek povolenych balikov na zaklade urcitych podmienok.
Pre ukazku bude stacit jednoduche pole.
$bundles = [1, 2, 3, 4];
2. V BasePressenter-i vlozim tento zoznam do vsetkych sablon
abstract class BasePresenter extends UI\Presenter
{
/** @var App\Model\BundlesManager @inject */
public $bundles;
public function beforeRender()
{
parent::beforeRender();
$this->template->bundles = $this->bundles; // <-- Zoznam povolenych balikov vlozime do sablony
}
}
3. Vytvorim si metodu MyMacros …
namespace App\Macros;
use Latte\MacroNode;
use Latte\PhpWriter;
class MyMacros extends \Latte\Macros\MacroSet
{
public static function install(\Latte\Compiler $compiler)
{
$me = new static($compiler);
$me->addMacro('bundle',
array($me, 'bundleStart'),
array($me, 'bundleEnd')
);
return $me;
}
/**
* {if in_array($param, $bundles) ...}
*/
public function bundleStart(MacroNode $node, PhpWriter $writer)
{
return $writer->write('if (in_array(%node.args, $bundles)) {');
/**
* Toto mam este rozsirene o to, aby user s rolou 'superadmin' mal pristup aj k modulom,
* ktore su zakazane. Mozno by to ale bolo lepsie riesit uz v medeli BundlesManager.
*
* Takze ja tam mam:
* return $writer->write('if (in_array(%node.args, $bundles) || $user->isInRole(\'superadmin\')) {');
*/
}
/**
* {/if}
*/
public function bundleEnd(MacroNode $node, PhpWriter $writer)
{
return $writer->write('}');
}
}
… a zaregistrujem ju v config.neon
latte:
macros:
- App\Macros\MyMacros
4. Nasledne mozem pouzit kdekolvek v sablone
<a href="#" n:bundle="8">Button pre bundle číslo 8</a>
{bundle 3}
<div class="bundle-wrapper">
Dostupné len ak je povolený bundle číslo 3!
</div>
{/bundle}
Prosim Vas, ak mam nieco zle, alebo by sa nieco dalo pouzivat elegantnejsie, alebo mate niekto iny napada, sem s nim :) … rad sa priucim. Dakujem.
Editoval vladimir.biro (24. 11. 2017 11:28)
- blaztar
- Člen | 93
V Nette 2.4 je ještě nový operátor „in“ v Latte. Ale nevím jak moc je to použitelné, mě to moc nefungovalo co jsem zkoušel, takže to v reálu snad nikde nepoužívám.
// nefunguje
<div n:if="4 in [1,2,4]"></div>
// funguje
{var $four = 4}
<div n:if="$four in [1,2,4]"></div>
// nefunguje
{var $four = 4}
{var $array = [1,2,4]}
<div n:if="$four in $array"></div>
I když místo rady pro tebe bych spíš já potřeboval osvětlit jak se to používá. :)
- vladimir.biro
- Člen | 163
blaztar napsal(a):
V Nette 2.4 je ještě nový operátor „in“ v Latte. Ale nevím jak moc je to použitelné, mě to moc nefungovalo co jsem zkoušel, takže to v reálu snad nikde nepoužívám.
// nefunguje <div n:if="4 in [1,2,4]"></div> // funguje {var $four = 4} <div n:if="$four in [1,2,4]"></div> // nefunguje {var $four = 4} {var $array = [1,2,4]} <div n:if="$four in $array"></div>
I když místo rady pro tebe bych spíš já potřeboval osvětlit jak se to používá. :)
To uz je podla toho, ako to spracovava macro if
Ked do parametra zadas $four in [1,2,3,4] tak do sablony sa vyrenderuje PHP kod
if (in_array($four, [1,2,3,4], TRUE)) { … } co PHP v pohode spracuje.
No ked zadas 4 in [1,2,3,4] parameter vobec nezmeni a do sablony vygeneruje if (4 in [1,2,3,4]) { … } co PHP nepzna a vyhodi to chybu.
Preco je tomu tak sa asi netreba zamyslat a pozuvat namiesto toho n:if=„in_array(4, [1,2,3,4])“
:)
Editoval vladimir.biro (24. 11. 2017 22:15)