Modelul componentelor

Un concept important în Nette este cel de componentă. Inserăm componente vizuale interactive în pagini, formulare sau toate elementele acestora sunt, de asemenea, componente. Există două clase de bază din care moștenesc toate aceste componente, fac parte din pachetul nette/component-model și sunt responsabile pentru crearea ierarhiei arborelui de componente.

Componenta

Nette\ComponentModel\Component este strămoșul comun al tuturor componentelor. Acesta conține metoda getName() care returnează numele componentei și metoda getParent() care returnează părintele acesteia. Ambele pot fi setate cu metoda setParent() – primul parametru este părintele, iar al doilea este numele componentei.

lookup (string $type): ?Component

Caută în ierarhie un obiect din clasa sau interfața dorită. De exemplu, $component->lookup(Nette\Application\UI\Presenter::class) returnează presenter dacă componenta este conectată la acesta, în ciuda mai multor niveluri.

lookupPath (string $type): ?string

Returnează așa-numita cale, care este un șir format prin concatenarea numelor tuturor componentelor de pe calea dintre componenta curentă și componenta căutată. Astfel, de exemplu, $component->lookupPath(Nette\Application\UI\Presenter::class) returnează identificatorul unic al componentei în raport cu prezentatorul.

Container

Nette\ComponentModel\Container este componenta părinte, adică componenta care conține copiii și care formează astfel structura arborescentă. Acesta dispune de metode pentru adăugarea, recuperarea și eliminarea cu ușurință a componentelor. Este strămoșul, de exemplu, al formularului sau al claselor Control și Presenter.

getComponent (string $name): ?Component

Returnează o componentă. Încercarea de a apela un copil nedefinit determină invocarea fabricii createComponent($name). Metoda createComponent($name) invocă metoda createComponent<component name> în componenta curentă și transmite numele componentei ca parametru. Componenta creată este apoi transmisă componentei curente ca fiind copilul său. Numim aceste fabrici de componente, ele pot fi implementate în clase moștenite de la Container.

getComponents(): array

Returnează descendenții direcți sub formă de matrice. Cheile conțin numele acestor componente. Notă: în versiunea 3.0.x, metoda returnează un iterator în loc de un tablou, iar primul parametru specifica dacă trebuie să se parcurgă componentele în profunzime, iar al doilea reprezenta un filtru de tip. Acești parametri sunt depreciați.

getComponentTree(): array

Returnează întreaga ierarhie de componente, inclusiv toate componentele copil imbricate, sub formă de matrice indexată. Căutarea se face mai întâi în profunzime.

Monitorizarea strămoșilor

Modelul de componente Nette permite lucrul foarte dinamic cu arborele (putem elimina, muta, adăuga componente), astfel încât ar fi o greșeală să ne bazăm pe faptul că, după crearea unei componente, părintele, părintele părintelui etc. sunt cunoscute imediat (în constructor). De obicei, părintele nu este cunoscut deloc atunci când este creată componenta.

Cum se poate afla când o componentă a fost adăugată în arborele de prezentare? Urmărirea modificării părintelui nu este suficientă, deoarece părintele părintelui ar fi putut fi atașat la prezentator, de exemplu. Metoda monitor($type, $attached, $detached) vă poate ajuta. Fiecare componentă poate monitoriza orice număr de clase și interfețe. Conectarea sau deconectarea este anunțată prin apelarea callback-urilor $attached și, respectiv, $detached, și prin transmiterea obiectului clasei monitorizate.

Un exemplu: Clasa UploadControl, care reprezintă elementul formular pentru încărcarea fișierelor în Nette Forms, trebuie să seteze atributul formularului enctype la valoarea multipart/form-data. Dar în momentul creării obiectului nu trebuie să fie atașată la nici un formular. Când trebuie modificat formularul? Soluția este simplă – creăm o cerere de monitorizare în constructor:

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

	// ...
}

iar atunci când formularul este disponibil, se apelează callback-ul. (Anterior, în schimb, se foloseau metodele comune attached și detached ).

versiune: 3.x