Modello a componenti

Un concetto importante in Nette è il componente. Inseriamo nelle pagine componenti visivi interattivi, i form sono componenti, così come tutti i loro elementi. Le due classi base da cui tutti questi componenti ereditano fanno parte del pacchetto nette/component-model e hanno il compito di creare una gerarchia ad albero di componenti.

Component

Nette\ComponentModel\Component è l'antenato comune di tutti i componenti. Contiene i metodi getName() che restituisce il nome del componente e il metodo getParent() che restituisce il suo genitore. Entrambi possono essere impostati con il metodo setParent() – il primo parametro è il genitore e il secondo il nome del componente.

lookup (string $type): ?Component

Cerca nella gerarchia verso l'alto un oggetto della classe o interfaccia richiesta. Ad esempio, $component->lookup(Nette\Application\UI\Presenter::class) restituisce il presenter, se il componente è collegato ad esso, anche attraverso diversi livelli.

lookupPath (string $type): ?string

Restituisce il cosiddetto percorso, che è una stringa creata concatenando i nomi di tutti i componenti nel percorso tra il componente corrente e quello cercato. Quindi, ad esempio, $component->lookupPath(Nette\Application\UI\Presenter::class) restituisce l'identificatore univoco del componente rispetto al presenter.

Container

Nette\ComponentModel\Container è il componente genitore, cioè un componente che contiene discendenti e forma così una struttura ad albero. Dispone di metodi per aggiungere, ottenere e rimuovere facilmente oggetti. È l'antenato, ad esempio, del form o delle classi Control e Presenter.

getComponent (string $name): ?Component

Restituisce un componente. Quando si tenta di ottenere un discendente non definito, viene chiamata la factory createComponent($name). Il metodo createComponent($name) chiama nel componente corrente il metodo createComponent<nomeComponente> e gli passa come parametro il nome del componente. Il componente creato viene quindi aggiunto al componente corrente come suo discendente. Questi metodi sono chiamati factory di componenti e possono essere implementati dai discendenti della classe Container.

getComponents(): array

Restituisce i discendenti diretti come array. Le chiavi contengono i nomi di questi componenti. Nota: nella versione 3.0.x il metodo restituiva un iteratore invece di un array e il suo primo parametro specificava se i componenti dovevano essere attraversati in profondità, e il secondo rappresentava un filtro di tipo. Questi parametri sono deprecati.

getComponentTree(): array

Ottiene l'intera gerarchia dei componenti, inclusi tutti i componenti figli annidati, come un array indicizzato. La ricerca va prima in profondità.

Monitoraggio degli antenati

Il modello a componenti di Nette consente un lavoro molto dinamico con l'albero (possiamo rimuovere, spostare, aggiungere componenti), quindi sarebbe un errore fare affidamento sul fatto che dopo la creazione del componente sia immediatamente noto (nel costruttore) il genitore, il genitore del genitore, ecc. Di solito, infatti, il genitore non è affatto noto al momento della creazione.

Come sapere quando un componente è stato collegato all'albero del presenter? Monitorare il cambiamento del genitore non è sufficiente, perché al presenter potrebbe essere stato collegato, ad esempio, il genitore del genitore. Il metodo monitor($type, $attached, $detached) aiuta. Ogni componente può monitorare un numero qualsiasi di classi e interfacce. L'allegamento o lo scollegamento viene segnalato chiamando il callback $attached rispettivamente $detached, e passando l'oggetto della classe monitorata.

Per una migliore comprensione, un esempio: la classe UploadControl, che rappresenta l'elemento del form per l'upload di file in Nette Forms, deve impostare l'attributo enctype del form sul valore multipart/form-data. Al momento della creazione dell'oggetto, tuttavia, potrebbe non essere collegata a nessun form. In quale momento, quindi, modificare il form? La soluzione è semplice: nel costruttore si richiede il monitoraggio:

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

	// ...
}

e non appena il form è disponibile, viene chiamato il callback. (In passato, al suo posto venivano usati i metodi comuni attached rispettivamente detached).

versione: 3.x