Modèle de composant
Un concept important dans Nette est le composant. Nous insérons des composants interactifs visuels dans les pages ; les formulaires ou tous
leurs éléments sont également des composants. Les deux classes de base dont tous ces composants héritent font partie du paquet
nette/component-model
et leur rôle est de créer une hiérarchie arborescente de composants.
Component
Nette\ComponentModel\Component
est l'ancêtre commun de tous les composants. Il contient les méthodes getName()
retournant le nom du composant et
la méthode getParent()
retournant son parent. Les deux peuvent être définis à l'aide de la méthode
setParent()
– le premier paramètre est le parent et le second est le nom du composant.
lookup (string $type): ?Component
Recherche dans la hiérarchie vers le haut un objet de la classe ou de l'interface demandée. Par exemple,
$component->lookup(Nette\Application\UI\Presenter::class)
retourne le presenter, si le composant y est attaché,
même à travers plusieurs niveaux.
lookupPath (string $type): ?string
Retourne ce qu'on appelle le chemin, qui est une chaîne formée en joignant les noms de tous les composants sur le chemin
entre le composant actuel et le composant recherché. Ainsi, par exemple,
$component->lookupPath(Nette\Application\UI\Presenter::class)
retourne l'identifiant unique du composant par
rapport au presenter.
Container
Nette\ComponentModel\Container
est le composant parent, c'est-à-dire un composant contenant des enfants et formant ainsi une structure arborescente. Il dispose
de méthodes pour ajouter, obtenir et supprimer facilement des objets. C'est l'ancêtre, par exemple, du formulaire ou des classes
Control
et Presenter
.
getComponent (string $name): ?Component
Retourne un composant. Lors d'une tentative d'obtention d'un enfant non défini, la factory createComponent($name)
est appelée. La méthode createComponent($name)
appelle la méthode
createComponent<NomDuComposant>
dans le composant actuel et lui passe le nom du composant en paramètre. Le
composant créé est ensuite ajouté au composant actuel en tant qu'enfant. Nous appelons ces méthodes des factories de
composants, et elles peuvent être implémentées par les descendants de la classe Container
.
getComponents(): array
Retourne les enfants directs sous forme de tableau. Les clés contiennent les noms de ces composants. Note : dans la version 3.0.x, la méthode retournait un itérateur au lieu d'un tableau, et son premier paramètre déterminait si les composants devaient être parcourus en profondeur, et le second représentait un filtre de type. Ces paramètres sont obsolètes.
getComponentTree(): array
Obtient toute la hiérarchie des composants, y compris tous les composants enfants imbriqués, sous forme de tableau indexé. La recherche se fait d'abord en profondeur.
Surveillance des ancêtres
Le modèle de composant de Nette permet un travail très dynamique avec l'arborescence (nous pouvons retirer, déplacer, ajouter des composants), il serait donc erroné de supposer qu'après la création d'un composant, le parent, le parent du parent, etc., sont immédiatement connus (dans le constructeur). La plupart du temps, le parent n'est pas du tout connu lors de la création.
Comment savoir quand un composant a été attaché à l'arborescence du presenter ? Surveiller le changement de parent ne
suffit pas, car le parent du parent, par exemple, aurait pu être attaché au presenter. La méthode monitor($type, $attached,
$detached) aide. Chaque composant peut surveiller n'importe quel nombre de classes et d'interfaces. L'attachement ou le
détachement est signalé en appelant le callback $attached
ou $detached
, respectivement, et en passant
l'objet de la classe surveillée.
Pour une meilleure compréhension, voici un exemple : la classe UploadControl
, représentant l'élément de
formulaire pour le téléchargement de fichiers dans Nette Forms, doit définir l'attribut enctype
du formulaire sur
multipart/form-data
. Cependant, au moment de la création de l'objet, il se peut qu'il ne soit attaché à aucun
formulaire. À quel moment alors modifier le formulaire ? La solution est simple – dans le constructeur, demandez la
surveillance :
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');
});
// ...
}
// ...
}
et dès que le formulaire est disponible, le callback est appelé. (Auparavant, les méthodes communes attached
ou
detached
étaient utilisées à la place).