Správa štítků s našeptávačem pro přidávaný štítek
- scientific
- Člen | 93
Mám Nette web a potřeboval bych do něj přidat k uživatelům štítky. Formou, že by se pomocí našeptávače našel štítek, kliknutím na něj by se k uživateli ten štítek přiřadil zobrazením v editaci uživatele, kdy by se zase dal odebrat kliknutím na „x“ u každého ze štítků.
Chci se zeptat, jestli to nette umí nějak jednoduše, či bych to musel programovat nějak složitě?
Děkuji za informace, případně nějaké informace/odkazy, které by mi nejak pomohli to zařídit, aby to fungovalo jak požaduji.
- Pavel Kravčík
- Člen | 1182
Hledáš pravděpodobně „multiselect dropdown“ (například).
Nebo třeba snadná alternativa může být obyčejný autocomplete s onchange, který to přes AJAX dá do DB a překreslí snippet, kde bude jen jeden foreach.
OT: Já bych řekl, že 95% ohledně programování jsou jednoduché a zároveň složité.
- dakur
- Člen | 493
Pokud používáš nějaký build stack (webpack/vitejs/…), můžeš zkusit react-select.
Editoval dakur (27. 3. 8:39)
- m.brecher
- Generous Backer | 765
@scientific
Chci se zeptat, jestli to nette umí nějak jednoduše
Nette ajax snippety + Naja.js tohle umí, je to standardní nette technologie, ale moc jednoduché pro nováčka to není. Nicméně zvládnout se to dá a posune Tě to vpřed.
Šel bych na to třeba tak, že bych našeptávač v první verzi vynechal a dal tam obyčejný select, ale bez formuláře, který po výběru odešle javascriptový request – signál do handleru presenteru Nette. Handler uloží se štítek do databáze a překreslí štítkovou lištu. Štítky budou v sobě mít každý malý odkaz <a …> se signálem pro mazání štítku a zpracují se rovněž ajaxově pomocí Naja.
Takže velmi stručně by postup byl cca tento:
- v šabloně vytvořit lištu pro uživatele
- do lišty vykreslíš sadu štítků uživatele
- do lišty přidáš také neformulářový select pro výběr štítku
- lištu obalíš snippetem pro překreslení https://doc.nette.org/…ication/ajax#…
- vložíš script Naja.js https://doc.nette.org/…ication/ajax#…
- navěsíš na onchange selectu makeRequest z Naja.js, odesílat signál pro vložení štítku https://naja.js.org/#…
- všechny odesílané ajax signály zpracuje centrálně jeden presenter handle https://doc.nette.org/…n/components#…
- handle signálu v presenteru bude volat model, který bude přidávat/mazat štítek uživatele
- potřebuješ do handle předat tři parametry (a) $userId, (b) $action = create|delete, ( c ) $labelId
- parametry musí mít absolutní nette cestu, tu získáš takto: https://doc.nette.org/…ication/ajax#…
- pro mazání štítků přidej do štítků ajax odkaz s křížkem, který bude odesílat ajaxový signál pro mazání
Takže navrhuji vše zpracovat jedním presenter handlem např:
public function handleLabel(int $userId, string $action, ?int $labelId = null): void
{
if($action === 'create'){
// přidání
}
if($action === 'delete'){
// mazání
}
}
Ideální je celou štítkovou lištu řídit a vykreslovat samostatnou komponentou zcela oddělenou od presenteru. Je to o malinko složitější, ale modernější. Potom by handle byl umístěný v komponentě a komponenta by celou lištu vykreslovala. Presenter by pouze komponentu vytvořil.
Pokud se vydáš moderní cestou komponent, tak pokud bys chtěl štítky editovat ve výpise více uživatelů, potom bys $userId získal v cyklu v latte šabloně a předáš přímo do metody render() komponenty:
{foreach $users as $id => $user}
{* some coding here.. *}
{control 'userLabel', userId: $id}
{/foreach}
Komponenta by vypadala cca nějak takhle:
class UserLabelControl extends UI\Control
{
public function __construct(private LabelModel $labelModel)
{}
// handle jako v presenteru
public function render(int $userId): void
{
// předat proměnné pro vykreslení
$this->template->render(__DIR__.'/templates/userLabelControl.latte'); // šablona v podadresáři vedle komponenty
}
}
A šablona komponenty vykreslí celou lištu štítků, je potřeba ji obalit do nějakého snippetu:
{snippet 'control'}
<div class='label-container'>
{foreach $labels as $id => $label}
<div class='label'>
<span>{$label->title}</span>
<a n:href="label!, ...$params" class="ajax">x</a> {* ajaxové mazání *}
</div>
{/foreach}
{* zde se vloží select *}
</div>
{/snippet}
Lišta formou komponenty se překresluje tak, že se překreslí celá tato komponenta:
$presenter['userLabel']->redrawControl();
Nette překreslí lištu tak, že překreslí všechny snippety v šabloně komponenty, proto v šabloně komponenty musí snippet být, ale na jeho názvu nezáleží.
Pozor! pokud se bude editovat ve výpise uživatelů, potom se předává v latte parametr do šablony komponenty, ale při překreslení se tento parametr nepředá (viz dokumentace: https://doc.nette.org/…ication/ajax#…). Proto při použití komponenty v cyklu uživatelů nepřekresluj komponentu, ale celý výpis uživatelů:
{* šablona akce presenteru *}
{snippet 'userContainer'}
{foreach $users as $id => $user}
{* some coding here.. *}
{control 'userLabel', userId: $id}
{/foreach}
{/snippet}
a v handle komponenty:
if($this->presenter->isAjax()){
$this->presenter->redrawControl('userContainer')
}