Správa štítků s našeptávačem pro přidávaný štítek

scientific
Člen | 93
+
0
-

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

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

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

@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')
}