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).

različica: 3.x