Component Model

An important concept in Nette is the component. We insert visual interactive components into pages, forms or all their elements are also components. There are two basic classes from which all these components inherit, are part of the nette/component-model package and are responsible for creating the component tree hierarchy.

Component

Nette\ComponentModel\Component is the common ancestor of all components. It contains the getName() method returning the name of the component and the getParent() method returning its parent. Both can be set with the setParent() method – the first parameter is the parent and the second is the component name.

lookup(string $type): ?Component

Searches up the hierarchy for an object of the desired class or interface. For example, $component->lookup(Nette\Application\UI\Presenter::class) returns presenter if the component is connected to it, despite several levels.

lookupPath(string $type): ?string

Returns the so-called path, which is a string formed by concatenating the names of all components on the path between the current component and the component being searched for. So, for example, $component->lookupPath(Nette\Application\UI\Presenter::class) returns the unique identifier of the component relative to the presenter.

Container

Nette\ComponentModel\Container is the parent component, i.e. the component containing the children and thus forming the tree structure. It has methods for easily adding, retrieving and removing components. It is the ancestor of, for example, the form or classes Control and Presenter.

getComponent(string $name): ?Component

Returns a component. Attempt to call undefined child causes invoking of factory createComponent($name). Method createComponent($name) invokes method createComponent<component name> in current component and it passes name of the component as a parameter. Created component is then passed to current component as its child. We call theese component factories, they can be implemented in classes inherited from Container.

getComponents(): array

Returns direct descendants as an array. The keys contain the names of these components. Note: in version 3.0.x, the method returned an iterator instead of an array, and its first parameter specified whether to iterate through the components in depth, and the second represented a type filter. These parameters are deprecated.

getComponentTree(): array

Returns the entire hierarchy of components, including all nested child components as indexed array. The search goes in depth first.

Monitoring of Ancestors

The Nette component model allows for very dynamic tree work (we can remove, move, add components), so it would be a mistake to rely on the fact that after creating a component, the parent, parent's parent, etc. are known immediately (in the constructor). Usually the parent is not known at all when the component is created.

How to find out when a component has been added to the presenter tree? Keeping track of the parent change is not enough, because the parent of the parent could have been attached to the presenter, for example. The monitor($type, $attached, $detached) method can help. Each component can monitor any number of classes and interfaces. Connection or disconnection is announced by calling the callbacks $attached and $detached, respectively, and passing the object of the monitored class.

An example: Class UploadControl, representing form element for uploading files in Nette Forms, has to set form's attribute enctype to value multipart/form-data. But in the time of the creation of the object it does not have to be attached to any form. When to modify the form? The solution is simple – we create a request for monitoring in the 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');
		});
		// ...
	}

	// ...
}

and when the form is available, the callback is called. (Previously, the common methods attached and detached were used instead.)

version: 3.x