Modelul de componente

Un concept important în Nette este componenta. În pagini inserăm componente vizuale interactive, componente sunt și formularele sau toate elementele lor. Cele două clase de bază, din care moștenesc toate aceste componente, fac parte din pachetul nette/component-model și au rolul de a crea o ierarhie arborescentă de componente.

Component

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

lookup (string $type): ?Component

Caută în ierarhie în sus un obiect de clasa sau interfața dorită. De exemplu, $component->lookup(Nette\Application\UI\Presenter::class) returnează presenter-ul, dacă componenta este atașată la acesta, chiar și prin mai multe niveluri.

lookupPath (string $type): ?string

Returnează așa-numita cale, care este un șir de caractere format prin concatenarea numelor tuturor componentelor de pe calea dintre componenta curentă și cea căutată. Deci, de exemplu, $component->lookupPath(Nette\Application\UI\Presenter::class) returnează un identificator unic al componentei față de presenter.

Container

Nette\ComponentModel\Container este componenta părinte, adică o componentă care conține descendenți și formează astfel o structură arborescentă. Dispune de metode pentru adăugarea, obținerea și eliminarea ușoară a obiectelor. Este strămoșul, de exemplu, al formularului sau al claselor Control și Presenter.

getComponent (string $name): ?Component

Returnează componenta. La încercarea de a obține un descendent nedefinit, este apelată fabrica createComponent($name). Metoda createComponent($name) apelează în componenta curentă metoda createComponent<nume componenta> și îi transmite ca parametru numele componentei. Componenta creată este apoi adăugată la componenta curentă ca descendent al acesteia. Aceste metode le numim fabrici de componente și pot fi implementate de descendenții clasei Container.

getComponents(): array

Returnează descendenții direcți ca array. Cheile conțin numele acestor componente. Notă: în versiunea 3.0.x, metoda returna un iterator în loc de array, iar primul său parametru specifica dacă componentele trebuie parcurse în adâncime, iar al doilea reprezenta un filtru de tip. Acești parametri sunt depreciați.

getComponentTree(): array

Obține întreaga ierarhie de componente, inclusiv toate componentele subordonate imbricate, ca un array indexat. Căutarea se face mai întâi în adâncime.

Monitorizarea strămoșilor

Modelul de componente Nette permite o muncă foarte dinamică cu arborele (putem elimina, muta, adăuga componente), de aceea ar fi o greșeală să ne bazăm pe faptul că, după crearea componentei, părintele, părintele părintelui etc. sunt imediat cunoscuți (în constructor). De obicei, părintele nu este deloc cunoscut la creare.

Cum să aflăm când a fost componenta atașată la arborele presenter-ului? Urmărirea schimbării părintelui nu este suficientă, deoarece la presenter ar fi putut fi atașat, de exemplu, părintele părintelui. Ajută metoda monitor($type, $attached, $detached). Fiecare componentă poate monitoriza orice număr de clase și interfețe. Atașarea sau detașarea este anunțată prin apelarea callback-ului $attached respectiv $detached, și transmiterea obiectului clasei monitorizate.

Pentru o mai bună înțelegere, un exemplu: clasa UploadControl, reprezentând elementul de formular pentru încărcarea fișierelor în Nette Forms, trebuie să seteze atributul enctype al formularului la valoarea multipart/form-data. Dar în momentul creării obiectului, este posibil să nu fie atașată la niciun formular. În ce moment, deci, să modificăm formularul? Soluția este simplă – în constructor se solicită monitorizarea:

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

	// ...
}

și de îndată ce formularul este disponibil, se apelează callback-ul. (Anterior, în locul său se folosea metoda comună attached respectiv detached).

versiune: 3.x