Model komponente
Pomemben koncept v Nette je komponenta. Vizualne
interaktivne komponente vstavljamo v strani, obrazci ali vsi njihovi elementi so prav tako komponente. Obstajata dva osnovna
razreda, od katerih dedujejo vse te komponente, ki sta del paketa nette/component-model
in sta odgovorna za
ustvarjanje drevesne hierarhije komponent.
Komponenta
Nette\ComponentModel\Component je
skupni prednik vseh komponent. Vsebuje metodo getName()
, ki vrača ime komponente, in metodo
getParent()
, ki vrača njenega starša. Oba lahko nastavite z metodo setParent()
– prvi parameter je
starš, drugi pa ime komponente.
lookup(string $type): ?Component
V hierarhiji poišče objekt želenega razreda ali vmesnika. Na primer,
$component->lookup(Nette\Application\UI\Presenter::class)
vrne presenter, če je komponenta kljub več ravnem
povezana z njim.
lookupPath(string $type): ?string
Vrne tako imenovano pot, ki je niz, sestavljen z združitvijo imen vseh komponent na poti med trenutno komponento in iskano
komponento. Tako na primer $component->lookupPath(Nette\Application\UI\Presenter::class)
vrne enolični
identifikator komponente glede na predvajalnik.
Kontejner
Nette\ComponentModel\Container je
nadrejena komponenta, tj. komponenta, ki vsebuje otroke in tako tvori drevesno strukturo. Ima metode za enostavno dodajanje,
iskanje in odstranjevanje komponent. Je prednik na primer obrazca ali razredov Control
in Presenter
.
getComponent(string $name): ?Component
Vrne komponento. Poskus klica nedefiniranega otroka povzroči klic tovarne createComponent($name).
Metoda createComponent($name)
prikliče metodo createComponent<component name>
v trenutni
komponenti in ji kot parameter posreduje ime komponente. Ustvarjena komponenta se nato posreduje trenutni komponenti kot njen
otrok. Te tovarne komponent imenujemo tovarne komponent, ki jih lahko implementiramo v razredih, podedovanih iz
Container
.
getComponents(): array
Vrne neposredne potomce kot polje. Ključi vsebujejo imena teh komponent. Opomba: v različici 3.0.x je metoda namesto polja vrnila iterator, njen prvi parameter pa je določal, ali naj se komponente iterira po globini, drugi pa je predstavljal filter tipa. Ta parametra sta zastarela.
getComponentTree(): array
Vrne celotno hierarhijo komponent, vključno z vsemi ugnezdenimi podrejenimi komponentami, kot indeksirano polje. Iskanje gre najprej v globino.
Spremljanje prednikov
Model komponent Nette omogoča zelo dinamično delo z drevesom (komponente lahko odstranjujemo, premikamo, dodajamo), zato bi bilo napačno, če bi se zanašali na to, da so po ustvarjanju komponente takoj (v konstruktorju) znani starši, starši staršev itd. Običajno starš ob ustvarjanju komponente sploh ni znan.
Kako ugotoviti, kdaj je bila komponenta dodana v drevo predstavitve? Spremljanje spremembe starša ni dovolj, saj bi bil lahko
na primer starš starša priložen predstavniku. V pomoč je lahko metoda monitor($type, $attached,
$detached). Vsaka komponenta lahko spremlja poljubno število razredov in vmesnikov. Priključitev ali odklop se najavi
s klicem povratnih klicev $attached
oziroma $detached
, pri čemer se posreduje objekt spremljanega
razreda.
Primer: Razred UploadControl
, ki predstavlja element obrazca za nalaganje datotek v Nette Forms, mora nastaviti
atribut obrazca enctype
na vrednost multipart/form-data
. Toda v času ustvarjanja objekta mu ni treba
biti priključen na noben obrazec. Kdaj spremeniti obrazec? Rešitev je preprosta – v konstruktorju ustvarimo zahtevo za
spremljanje:
class UploadControl extends Nette\Forms\Controls\BaseControl
{
public function __construct($label)
{
$this->monitor(Nette\Forms\Form::class, function ($form): void {
$form->setHtmlAttribute('enctype', 'multipart/form-data');
});
// ...
}
// ...
}
in ko je obrazec na voljo, se pokliče povratni klic. (Prej smo namesto tega uporabljali običajni metodi attached
in detached
.)