Komponentni model
Pomemben pojem v Nette je komponenta. V strani vstavljamo vizualne interaktivne komponente, komponente so tudi obrazci ali vsi
njihovi elementi. Osnovna dva razreda, od katerih vse te komponente dedujejo, sta del paketa nette/component-model
in
imata nalogo ustvarjati drevesno hierarhijo komponent.
Component
Nette\ComponentModel\Component
je skupni prednik vseh komponent. Vsebuje metodi getName()
, ki vrača ime komponente, in metodo
getParent()
, ki vrača njenega starša. Oboje lahko nastavimo z metodo setParent()
– prvi parameter
je starš in drugi ime komponente.
lookup (string $type): ?Component
V hierarhiji navzgor poišče objekt zahtevanega razreda ali vmesnika. Na primer
$component->lookup(Nette\Application\UI\Presenter::class)
vrne presenter, če je komponenta nanj, tudi preko več
nivojev, priključena.
lookupPath (string $type): ?string
Vrača t.i. pot, kar je niz, nastal s spajanjem imen vseh komponent na poti med trenutno in iskano komponento. Torej npr.
$component->lookupPath(Nette\Application\UI\Presenter::class)
vrača edinstven identifikator komponente glede na
presenter.
Container
Nette\ComponentModel\Container
je starševska komponenta, tj. komponenta, ki vsebuje potomce in tako tvori drevesno strukturo. Ima metode za enostavno dodajanje,
pridobivanje in odstranjevanje objektov. Je prednik na primer obrazca ali razredov Control
in
Presenter
.
getComponent (string $name): ?Component
Vrača komponento. Pri poskusu pridobivanja nedefiniranega potomca se pokliče tovarna createComponent($name)
.
Metoda createComponent($name)
v trenutni komponenti pokliče metodo
createComponent<ime komponente>
in ji kot parameter posreduje ime komponente. Ustvarjena komponenta se nato
doda v trenutno komponento kot njen potomec. Tem metodam rečemo tovarne komponent in jih lahko implementirajo potomci razreda
Container
.
getComponents(): array
Vrača neposredne potomce kot polje. Ključi vsebujejo imena teh komponent. Opomba: v različici 3.0.x je metoda namesto polja vračala iterator in njen prvi parameter je določal, ali naj se komponente prehajajo v globino, drugi pa je predstavljal tipski filter. Ti parametri so zastareli.
getComponentTree(): array
Pridobi celotno hierarhijo komponent, vključno z vsemi gnezdenimi podrejenimi komponentami, kot indeksirano polje. Iskanje gre najprej v globino.
Spremljanje prednikov
Komponentni model Nette omogoča zelo dinamično delo z drevesom (komponente lahko odstranjujemo, premikamo, dodajamo), zato bi bila napaka zanašati se na to, da je po ustvarjanju komponente takoj (v konstruktorju) znan starš, starš starša itd. Večinoma namreč starš ob ustvarjanju sploh ni znan.
Kako ugotoviti, kdaj je bila komponenta priključena v drevo presenterja? Spremljanje spremembe starša ni dovolj, saj je bil
lahko k presenterju priključen na primer starš starša. Pomaga metoda monitor($type, $attached,
$detached). Vsaka komponenta lahko spremlja poljubno število razredov in vmesnikov. Priključitev ali odklop je sporočen
s klicem povratnega klica $attached
oz. $detached
, in posredovanjem objekta spremljanega razreda.
Za boljše razumevanje primer: razred UploadControl
, ki predstavlja obrazčevni element za nalaganje datotek
v Nette Forms, mora obrazcu nastaviti atribut enctype
na vrednost multipart/form-data
. V času
ustvarjanja objekta pa ni nujno, da je priključen na kakršenkoli obrazec. V katerem trenutku torej modificirati obrazec?
Rešitev je enostavna – v konstruktorju se zahteva 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 takoj ko je obrazec na voljo, se pokliče povratni klic. (Prej se je namesto njega uporabljala skupna metoda
attached
oz. detached
).