Modello di componente
Un concetto importante in Nette è quello di componente. Inseriamo componenti interattivi visivi nelle pagine, i moduli o tutti i loro
elementi sono anch'essi componenti. Esistono due classi di base da cui ereditano tutti i componenti, che fanno parte del
pacchetto nette/component-model
e sono responsabili della creazione della gerarchia ad albero dei componenti.
Component
Nette\ComponentModel\Component è
l'antenato comune di tutti i componenti. Contiene il metodo 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 un oggetto della classe o dell'interfaccia desiderata. Ad esempio,
$component->lookup(Nette\Application\UI\Presenter::class)
restituisce presenter se il componente è collegato ad
esso, nonostante i diversi livelli.
lookupPath(string $type): ?string
Restituisce il cosiddetto percorso, che è una stringa formata dalla concatenazione dei nomi di tutti i componenti del
percorso tra il componente corrente e il componente cercato. Quindi, ad esempio,
$component->lookupPath(Nette\Application\UI\Presenter::class)
restituisce l'identificatore univoco del componente
relativo al presentatore.
Container
Nette\ComponentModel\Container è il
componente genitore, cioè il componente che contiene i figli e che quindi forma la struttura ad albero. Dispone di metodi per
aggiungere, recuperare e rimuovere facilmente i componenti. È l'antenato, ad esempio, del modulo o delle classi
Control
e Presenter
.
getComponent(string $name): ?Component
Restituisce un componente. Il tentativo di chiamare un figlio non definito causa l'invocazione del factory createComponent($nome).
Il metodo createComponent($name)
invoca il metodo createComponent<component name>
nel componente
corrente e passa il nome del componente come parametro. Il componente creato viene quindi passato al componente corrente come suo
figlio. Questi factory di componenti possono essere implementati in classi ereditate da Container
.
getComponents(): array
Restituisce i discendenti diretti come array. Le chiavi contengono i nomi dei componenti. Nota: nella versione 3.0.x, il metodo restituiva un iteratore invece di un array e il primo parametro specificava se iterare i componenti in profondità e il secondo rappresentava un filtro di tipo. Questi parametri sono deprecati.
getComponentTree(): array
Restituisce l'intera gerarchia di componenti, compresi tutti i componenti figli annidati, come array indicizzato. La ricerca va prima in profondità.
Monitoraggio degli antenati
Il modello dei componenti di Nette consente di lavorare in modo molto dinamico sull'albero (si possono rimuovere, spostare, aggiungere componenti), quindi sarebbe un errore fare affidamento sul fatto che dopo la creazione di un componente, il genitore, il genitore del genitore, ecc. siano noti immediatamente (nel costruttore). Di solito il genitore non è noto al momento della creazione del componente.
Come scoprire quando un componente è stato aggiunto all'albero del presentatore? Tenere traccia del cambiamento del genitore
non è sufficiente, perché il genitore del genitore potrebbe essere stato aggiunto al presentatore, ad esempio. Il metodo monitor($type, $attached,
$detached) può aiutare. Ogni componente può monitorare un numero qualsiasi di classi e interfacce. La connessione o la
disconnessione vengono annunciate chiamando le callback $attached
e $detached
, rispettivamente, e
passando l'oggetto della classe monitorata.
Un esempio: La classe UploadControl
, che rappresenta l'elemento modulo per il caricamento dei file in Nette Forms,
deve impostare l'attributo enctype
del modulo sul valore multipart/form-data
. Ma al momento della
creazione dell'oggetto non deve essere collegata ad alcun modulo. Quando modificare il modulo? La soluzione è semplice: si crea
una richiesta di monitoraggio nel costruttore:
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 quando il modulo è disponibile, viene richiamato il callback. (In precedenza, si usavano invece i metodi comuni
attached
e detached
).