Předání povinných parametrů komponentě

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
artemevsin
Člen | 61
+
0
-

Ahoj,
vytvářím trochu komplikovanější strom komponent:

-- wrapper
---- seznam položek (listControl)
---- položka (detailControl)
------ popis
------ komentáře
------ formulář na úpravu položky

Seznam položek načítá položky ze systému a vykreslí je. V seznamu je handleClick(), který reaguje na kliknutí na položku a zavolá událost onItemClick() na wrapperu, který zavolá redraw Položky.

Otázka je, jak předat konkrétní položku (pro zjednodušení její ID) komponentě detailControl z listControl.
Zatím jsem přišel na tři možnosti:

  1. generovaná továrnička + ‚vytažení‘ ID z listControlu (případně jinak předat ID továrně)
<?php
interface IDetailControlFactory {
    /** @return DetailControl */
    function create($id);
}

class WrapperControl extends Control {
    /**
     * @var IDetailControlFactory
     */
    private $detailControlFactory;
    /**
     * @var ListControl
     */
    private $listControl;

    /**
     * WrapperControl constructor.
     * @param IDetailControlFactory $detailControlFactory
     * @param ListControl $listControl
     */
    public function __construct(IDetailControlFactory $detailControlFactory, ListControl $listControl)
    {
        $this->detailControlFactory = $detailControlFactory;
        $this->listControl = $listControl;
    }

    protected function createComponentDetailControl()
    {
        return $this->detailControlFactory->create($this['listControl']->getDetailId());
    }

    protected function createComponentListControl()
    {
        return $this->listControl;
    }
}

?>
  1. vyžádání uvnitř komponenty v metodě attached()
<?php
class DetailControl extends Control {

    public function __construct()
    {
        $this->monitor(WrapperControl::class);
    }

    protected function attached($control)
    {
        if ($control instanceof WrapperControl) {
            $this->item = $control->getItem();
        }
    }
}

class WrapperControl extends Control {

    public function getItem()
    {
        return $this['listControl']->getDetailId();
    }
}
?>
  1. nastavení DetailId přes setter:
<?php
class WrapperControl {
    /**
     * @var ListControl
     */
    private $listControl;
    /**
     * @var DetailControl
     */
    private $detailControl;

    /**
     * WrapperControl constructor.
     * @param DetailControl $detailControl
     * @param ListControl $listControl
     */
    public function __construct(DetailControl $detailControl, ListControl $listControl)
    {
        $this->listControl = $listControl;
        $this->detailControl = $detailControl;
    }

    protected function createComponentDetailControl()
    {
        $this->detailControl->setDetailId($this['listControl']->getDetailId());
        return $this->detailControl;
    }

    protected function createComponentListControl()
    {
        return $this->listControl;
    }
}

?>

Asi nejlepší a nejčistší je 1. možnost, ale je tam nutnost vytváření továrničky, která zas ale bude vyžadovat ten parametr už při vytvoření objektu.

Mně se víc líbí 2. možnost, kdy je ten parametr vyžadován přímo v továrničce po připojení k rodičovské komponentě. Ta metoda se zavolá vždy, takže je tam taky jistota toho, že pokud rodič ten parametr má, bude schopen ho předat i komponentě detailControl. Jen ta kontrola se provádí o něco později než v prvním případě.

No a třetí možnost se mi líbí ze všech nejméně – není zde žádné explicitní vyžadování parametru.

Jak toto řešíte vy? Jaká je best-practice při vytváření takto vnořených komponent?

Editoval artemevsin (14. 4. 2016 14:45)

David Matějka
Moderator | 6445
+
0
-

Preferoval bych tu prvni moznost.

A mimochodem, ve WrapperControl si vyzadujes jako zavislost ListControl. To se bere odkud? Mel by sis na to pravdepodobne taky napsat tovarnu.

artemevsin
Člen | 61
+
0
-

ListControl je služba zaregistrovaná v configu a dědí od Nette\Application\UI\Control.

Takže pro každou komponentu musím napsat i továrničku? To Item se totiž pak předává do komponenty pro popis, komentáře i formulář pro úpravu položky

David Matějka
Moderator | 6445
+
+1
-

jj, pro kazdou komponentu vytvarej tovarnu. Komponenty nemaji byt jako sluzby, zpusobovalo by to problemy

artemevsin
Člen | 61
+
0
-

ok, mockrát díky!

mohl bys naznačit, jaké problémy to může způsobovat?

David Matějka
Moderator | 6445
+
+1
-

Jedna instance komponenty muze byt pripojena do stromu komponent pouze jednou. Nemohl bys ji tedy pouzit vicekrat na jedne strance, pripadne kdyby doslo k internimu presmerovani na jiny presenter (treba v ramci chyby), tak by to taky nefungovalo.

artemevsin
Člen | 61
+
0
-

super, ještě jednou díky :)