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

version: 3.x