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