Komponens modell

A Nette egyik fontos fogalma a komponens. Vizuális interaktív komponenseket illesztünk be az oldalakba, űrlapokba, illetve azok minden eleme is komponens. Két alaposztály van, amelyektől az összes ilyen komponens öröklődik, a nette/component-model csomag részét képezik, és a komponensfa hierarchiájának létrehozásáért felelősek.

Component

Nette\ComponentModel\Component az összes komponens közös őse. Tartalmazza a getName() metódust, amely a komponens nevét adja vissza, és a getParent() metódust, amely a szülőjét adja vissza. Mindkettő a setParent() metódussal állítható be – az első paraméter a szülő, a második pedig a komponens neve.

lookup(string $type): ?Component

A hierarchiában felfelé keres egy objektumot a kívánt osztályból vagy interfészből. Például a $component->lookup(Nette\Application\UI\Presenter::class) visszaadja a presenter-t, ha a komponens több szint ellenére is kapcsolódik hozzá.

lookupPath(string $type): ?string

Visszaadja az úgynevezett útvonalat, amely az aktuális komponens és a keresett komponens közötti útvonalon lévő összes komponens nevének összekapcsolásával képzett karakterlánc. Így például a $component->lookupPath(Nette\Application\UI\Presenter::class) a komponens egyedi azonosítóját adja vissza a bemutatóhoz képest.

Container

Nette\ComponentModel\Container a szülő komponens, azaz az a komponens, amely a gyermekeket tartalmazza, és így a fa szerkezetét alkotja. Módszerekkel rendelkezik a komponensek egyszerű hozzáadásához, visszakereséséhez és eltávolításához. Őse például az űrlapnak vagy a Control és a Presenter osztályoknak.

getComponent(string $name): ?Component

Visszaad egy komponenst. A nem definiált gyermek hívásának kísérlete a factory createComponent($name) meghívását okozza. A createComponent($name) metódus meghívja a metódust createComponent<component name> az aktuális komponensben, és paraméterként átadja a komponens nevét. A létrehozott komponens ezután átadásra kerül az aktuális komponensnek, mint annak gyermeke. Ezeket a komponens gyáraknak nevezzük, a Container-tól örökölt osztályokban implementálhatók.

getComponents(): array

Közvetlen leszármazottakat ad vissza tömbként. A kulcsok ezen komponensek nevét tartalmazzák. Megjegyzés: a 3.0.x verzióban a módszer tömb helyett egy iterátort adott vissza, és az első paramétere megadta, hogy a komponenseket mélységben iterálja-e, a második pedig egy típusszűrőt jelentett. Ezek a paraméterek elavultak.

getComponentTree(): array

Visszaadja a komponensek teljes hierarchiáját, beleértve az összes beágyazott gyermekkomponenst indexelt tömbként. A keresés először a mélységben történik.

Az ősök figyelése

A Nette komponensmodell nagyon dinamikus famunkát tesz lehetővé (komponenseket távolíthatunk el, mozgathatunk, adhatunk hozzá), ezért hiba lenne arra hagyatkozni, hogy egy komponens létrehozása után azonnal (a konstruktorban) ismert a szülő, a szülő szülője, stb. Általában a szülő egyáltalán nem ismert a komponens létrehozásakor.

Hogyan lehet megtudni, hogy egy komponens mikor került hozzá a prezenterfához? A szülő változásának nyomon követése nem elegendő, mert a szülő szülője például a prezenterhez csatolódhatott. A monitor($type, $attached, $detached) metódus segíthet. Minden komponens tetszőleges számú osztályt és interfészt monitorozhat. A csatlakozást vagy szétkapcsolódást a $attached illetve a $detached visszahívások meghívásával és a megfigyelt osztály objektumának átadásával jelentjük be.

Egy példa: A UploadControl osztály, amely a Nette Forms-ben a fájlok feltöltésére szolgáló űrlapelemet képviseli, az űrlap enctype attribútumát a multipart/form-data értékre kell állítani. Az objektum létrehozásakor azonban nem kell semmilyen űrlaphoz csatolni. Mikor kell módosítani az űrlapot? A megoldás egyszerű – a konstruktorban létrehozunk egy megfigyelési kérelmet:

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');
		});
		// ...
	}

	// ...
}

és amikor az űrlap elérhetővé válik, a visszahívást hívjuk meg. (Korábban a attached és a detached közös metódusokat használtuk helyette.)

verzió: 3.x