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