Jak spravne pouzivat komponenty – realny priklad

PytelCZ
Člen | 21
+
+1
-

Ahojte,
predem chci napsat, ze jsem posledni tri dny venoval procitani fora a hledani idealniho reseni, ale stale v tom plavu, tak doufam ze toto pomuze k ujasneni nejen me, ale i nekomu dalsimu. Nejlip vse chapu prikladem z praxe, prosim tedy o navedeni na spravne reseni.
Mam aplikaci, kde v administraci pracuji s budovami a ruznymi vecmi kolem nich. Tedy mam detail budovy, ktery je reseny pres zalozky, ty jsou napr. popis, technologie, zaruky, pristupy.
Vezmeme si treba zalozku pristupy, kde potrebuji zobrazit seznam pristupu do te budovy, ktery bude filtrovatelny a umozni mi pristup smazat/editovat. Tento seznam zaroven potrebuji mit i v hlavnim „menu“, kde ale budou veskere pristupy do vsech budov. Tedy to chci udelat do komponenty, s tim, ze v zalozce budovy bude v podstate jen predvoleny filtr pro konkretni budovu, jinak bude vse fungovat stejne jako v celkovem prehledu pristupu.
Moje idea je, ze udelam komponentu Pristup, ktera bude mit v sobe komponenty napr. PristupFiltr, PristupVypis, PristupDetail a v presenteru jen necham zobrazit komponentu Pristup (v presenteru objektu ji predam ID objektu).

Ztracim se v nekolika vecech:

  1. jak udelat korektne predavani dat? Tedy do komponenty Pristup si mam predat vsechny repository ktere potrebuju a tahat si data tady a ty nasledne predat podrizenym komponentam (jak presne?) nebo si tahat data az v konkretni podkomponente? Nebo tahat data v presenteru a predat je vsechny do komponenty Pristup a ta preda do podkomponent to co potrebuji? Jak?
  2. predpokladam, ze PristupFiltr bude mit persistentni parametry podle kterych se bude filtrovat. Jak ale komponenta PristupVypis zjisti co presne ma vypsat? To co ma vypsat ji dam rovnou jako data z komponenty Pristup? Ale jak v te komponente nactu spravne data dle nastaveni filtru?
  3. jak udelam, ze kdyz v komponente PristupVypis kliknu na editaci, zavola se mi komponenta PristupDetail a dostanou se do ni data pro editaci zvoleneho pristupu?

Doufam ze je to alespon trosku srozumitelne ;-)

manwe
Člen | 44
+
0
-

Asi bych to resil trochu jinak, k cemu konkretne bude treba komponenta PristupFiltr?

Udelal bych si komponenty

  1. BuildingAccessList
  2. BuildingAccessDetail

ad 1)
parametry muzes predavat vicemene dvemi zpusoby, a teoreticky to jde i kombinovat

  1. v render metode – parametry predavas v .latte, takze napriklad muzes v detailu budovy v zalozce Pristupy mit neco jako
{control accessList 'buildingId' => $building->id}

toto se pak preda do metody render($params = []) v komponente BuildingAccessList, takze v metode render pak muzes vzit ty data a podle toho udelat vyber. Velkou nevyhodou tohoto pristupu je ze se pri ajaxovych volanich neposilaji tyto parametry znova, takze pokud chces aby ti to fungovalo ajaxove, tak to pouzit nelze.

  1. pres konstruktor/metodu

v seznamu budov, budes asi potrebovat pouzit multiplikator, abys mohl pouzit vice komponent stejneho typu, takze budes mit neco jako

<div n:foreach="$buildings as $building">
	{control accessList-$building->id}
</div>

a v tom presenteru budes mit neco jako

public function createComponentAccessList(){
	return new UI\Multiplier($buildingId){ // tady se preda to $building->id
		$accessList = $this->accessListFactory()->create();
		$accessList->setBuildingId($buildingId);
		return $accessList;
	}
}
  1. BuildingAccessDetail
  • tady mas (asi, minimalne) dve moznosti – bud udelas Presenter/Akci na detail pristupu, nebo vyrenderujes tu komponentu nekam do modalniho okna (tak bych to delal ja, pokud to neobsahuje moc informaci).

Pokud to budes delat pres Presenter/Akci tak je to jednoduche, proste nekam hodis Link na dany presenter/akci
Pokud bys to chtel delat v modal oknu tak to budes muset rucne „pripojit“ k presenteru pres addComponent, s tim ze pokud bys chtel aby ti tam fungovala nejaka interakce (signaly, formulare, ajax) tak to budes muset uz k presenteru pripojit rychleji (napriklad v Action) a pote to vyrenderovat rucne pozdeji, jinak ti bude presenter rvat ze nezna tuto komponentu.
Pokud by te to zajimalo tak dej vedet, muzu postnout nejaky example jak to resim ja.

Editoval manwe (17. 5. 2019 10:46)

CZechBoY
Člen | 3608
+
0
-

Asi nemusíš jít až na takovou úroveň že bys měl každej řádek tabulky samotnou komponentu, klidně stačí mít jen tabulku jako komponentu.

Komponenta tabulky potom bude mít subkomponentu s filtrovacím formulářem a stránkováním. Samotná komponenta tabulky pak bude řídit tyhle komponenty – např. vytáhne si data z filtrovacího formuláře → vezme vyfiltrovaný data z → nastaví počet řádků do komponenty se stránkováním → vypíše data v šabloně.

Předávání přes render metodu určitě nedoporučuji, protože při ajaxovým volání se nepředávají parametry (prostě se zavolá jen render()) – možná to teď nepotřebuješ, ale v budoucnu se ti to třeba bude hodit.

Co by vlastně měla dělat ta komponenta PristupDetail? To je ten konkrétní řádek nebo nějaká full detail page se všemi informacemi? Jestli ten stejnej pohled nikde jinde nepoužíváš tak bych asi nedělal komponentu ale jen obyč PristupDetailPresenter.

PytelCZ
Člen | 21
+
0
-

manwe napsal(a):

Asi bych to resil trochu jinak, k cemu konkretne bude treba komponenta PristupFiltr?

Filtr nad vypisem seznamu tech pristupu. Chtel bych ho dat do komponenty, at ho muzu na kazde strance zobrazit na jinem miste, pripadne na strance objektu z toho filtru zrusit filtrovani dle objektu, zatimco na globalni strance pristupu tam filtr podle objektu bude.

O obou moznostech jak predavat parametry co jsi napsal vim, ale neni mi jasne, jak je predavat, kdyz to budu mit rozdelene do vice komponent jak jsem psal :(

Co se tyce detailu, mam to udelane jako samotnou stranku (modal nechci), tak mi jde o to, jak spravne z te komponenty udelat odkaz na druhou komponentu (nedelam odkaz na presenter, ale z komponenty na jinou komponentu) a potom zase po ulozeni/editaci se vratit na puvodni…

Ukazka, jak to je vypada vzhledove ted (aby byla lepsi predstava co chci), ale je to naprimo v presenteru a ne pres komponenty. Musel jsem nejake veci rozmazat kvuli klienta…

obrazek

  1. chtel bych taky jako komponentu udelat – z ciselniku nacita typy vstupu a zobrazuje zaroven jejich pocet, po kliknuti se vyfiltruje seznam
  2. filtr – komponenta
  3. vypis – komponenta
PytelCZ
Člen | 21
+
0
-

CZechBoY napsal(a):
Komponenta tabulky potom bude mít subkomponentu s filtrovacím formulářem a stránkováním. Samotná komponenta tabulky pak bude řídit tyhle komponenty – např. vytáhne si data z filtrovacího formuláře → vezme vyfiltrovaný data z → nastaví počet řádků do komponenty se stránkováním → vypíše data v šabloně.

Ano to je presne ono, ale jak to udelam? Mam takhle udelanou tu hlavni komponentu:

<?php
namespace App\AdminModule\Controls\Vstup;

use Nette\Application\UI\Control;

class VstupControl extends Control
{
    /** @var int */
    private $objectId;

    /** @var IVstupStavyControlFactory */
    private $vstupStavyControlFactory;

    /** @var IVstupFiltrControlFactory */
    private $vstupFiltrControlFactory;

    /** @var IVstupVypisControlFactory */
    private $vstupVypisControlFactory;

    public function __construct($objectId,
                                IVstupStavyControlFactory $vstupStavyControlFactory,
                                IVstupFiltrControlFactory $vstupFiltrControlFactory,
                                IVstupVypisControlFactory $vstupVypisControlFactory)
    {
        $this->vstupStavyControlFactory = $vstupStavyControlFactory;
        $this->vstupFiltrControlFactory = $vstupFiltrControlFactory;
        $this->vstupVypisControlFactory = $vstupVypisControlFactory;
        $this->objectId = $objectId;
    }

    public function render()
    {
        $this->template->setFile(__DIR__ . '/vstup.latte');
        $this->template->render();
    }

    protected function createComponentVstupStavy()
    {
        $control = $this->vstupStavyControlFactory->create();
        return $control;
    }

    protected function createComponentVstupFiltr()
    {
        $control = $this->vstupFiltrControlFactory->create();
        return $control;
    }

    protected function createComponentVstupVypis()
    {
        $control = $this->vstupVypisControlFactory->create();
        return $control;
    }
}
?>

Ale netusim jak prave udelat to predavani dat co jsi popsal :-)

Předávání přes render metodu určitě nedoporučuji, protože při ajaxovým volání se nepředávají parametry (prostě se zavolá jen render()) – možná to teď nepotřebuješ, ale v budoucnu se ti to třeba bude hodit.

Ano to jsem se taktez docetl ve foru ;-)

Co by vlastně měla dělat ta komponenta PristupDetail? To je ten konkrétní řádek nebo nějaká full detail page se všemi informacemi? Jestli ten stejnej pohled nikde jinde nepoužíváš tak bych asi nedělal komponentu ale jen obyč PristupDetailPresenter.

Tohle je nova stranka s vypisem toho konkretniho pristupu, kde je asi 30 ruznych parametru, ktere se u toho eviduji. Tedy normalni editace/vytvareni noveho zaznamu. Takze je to lepsi udelat jako samotny presenter?