Nette Documentation Preview

syntax
Modelo de Componente
********************

.[perex]
Um conceito importante no Nette é o componente. Inserimos [componentes interativos visuais |application:components] nas páginas, formulários são componentes, assim como todos os seus elementos. As duas classes base das quais todos esses componentes herdam fazem parte do pacote `nette/component-model` e têm a tarefa de criar uma hierarquia de componentes em árvore.


Component
=========
[api:Nette\ComponentModel\Component] é o ancestral comum de todos os componentes. Contém os métodos `getName()` que retorna o nome do componente e `getParent()` que retorna seu pai. Ambos podem ser definidos usando o método `setParent()` - o primeiro parâmetro é o pai e o segundo é o nome do componente.


lookup(string $type): ?Component .[method]
------------------------------------------
Procura na hierarquia para cima um objeto da classe ou interface solicitada. Por exemplo, `$component->lookup(Nette\Application\UI\Presenter::class)` retorna o presenter, se o componente estiver anexado a ele, mesmo através de vários níveis.


lookupPath(string $type): ?string .[method]
-------------------------------------------
Retorna o chamado caminho, que é uma string formada pela concatenação dos nomes de todos os componentes no caminho entre o componente atual e o componente procurado. Assim, por exemplo, `$component->lookupPath(Nette\Application\UI\Presenter::class)` retorna um identificador único do componente em relação ao presenter.


Container
=========
[api:Nette\ComponentModel\Container] é o componente pai, ou seja, um componente que contém descendentes e forma assim uma estrutura em árvore. Possui métodos para fácil adição, obtenção e remoção de objetos. É o ancestral, por exemplo, do formulário ou das classes `Control` e `Presenter`.


getComponent(string $name): ?Component .[method]
------------------------------------------------
Retorna um componente. Ao tentar obter um descendente indefinido, a fábrica `createComponent($name)` é chamada. O método `createComponent($name)` chama o método `createComponent<nome do componente>` no componente atual e passa o nome do componente como parâmetro. O componente criado é então adicionado ao componente atual como seu descendente. Chamamos esses métodos de fábricas de componentes e eles podem ser implementados por descendentes da classe `Container`.


getComponents(): array .[method]
--------------------------------
Retorna os descendentes diretos como um array. As chaves contêm os nomes desses componentes. Nota: na versão 3.0.x, o método retornava um iterador em vez de um array, e seu primeiro parâmetro determinava se os componentes deveriam ser percorridos em profundidade, e o segundo representava um filtro de tipo. Esses parâmetros estão obsoletos.


getComponentTree(): array .[method]{data-version:3.1.0}
-------------------------------------------------------
Obtém toda a hierarquia de componentes, incluindo todos os componentes filhos aninhados, como um array indexado. A busca é feita primeiro em profundidade.


Monitoramento de Ancestrais
===========================

O modelo de componente Nette permite um trabalho muito dinâmico com a árvore (podemos remover, mover, adicionar componentes), portanto seria um erro confiar que, após a criação de um componente, o pai, o pai do pai, etc., sejam imediatamente conhecidos (no construtor). Na maioria das vezes, o pai não é conhecido durante a criação.

Como saber quando um componente foi anexado à árvore do presenter? Observar a mudança do pai não é suficiente, porque o pai do pai pode ter sido anexado ao presenter, por exemplo. O método [monitor($type, $attached, $detached)|api:Nette\ComponentModel\Component::monitor()] ajuda. Cada componente pode monitorar qualquer número de classes e interfaces. A anexação ou desanexação é sinalizada chamando o callback `$attached` ou `$detached`, respectivamente, e passando o objeto da classe monitorada.

Para melhor compreensão, um exemplo: a classe `UploadControl`, que representa o elemento de formulário para upload de arquivos no Nette Forms, precisa definir o atributo `enctype` do formulário para o valor `multipart/form-data`. No entanto, no momento da criação do objeto, ele pode não estar anexado a nenhum formulário. Em que momento, então, modificar o formulário? A solução é simple - no construtor, solicita-se o monitoramento:

```php
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 assim que o formulário estiver disponível, o callback é chamado. (Anteriormente, os métodos comuns `attached` e `detached` eram usados em seu lugar).


{{leftbar: nette:@menu-topics}}

Modelo de Componente

Um conceito importante no Nette é o componente. Inserimos componentes interativos visuais nas páginas, formulários são componentes, assim como todos os seus elementos. As duas classes base das quais todos esses componentes herdam fazem parte do pacote nette/component-model e têm a tarefa de criar uma hierarquia de componentes em árvore.

Component

Nette\ComponentModel\Component é o ancestral comum de todos os componentes. Contém os métodos getName() que retorna o nome do componente e getParent() que retorna seu pai. Ambos podem ser definidos usando o método setParent() – o primeiro parâmetro é o pai e o segundo é o nome do componente.

lookup(string $type): ?Component

Procura na hierarquia para cima um objeto da classe ou interface solicitada. Por exemplo, $component->lookup(Nette\Application\UI\Presenter::class) retorna o presenter, se o componente estiver anexado a ele, mesmo através de vários níveis.

lookupPath(string $type): ?string

Retorna o chamado caminho, que é uma string formada pela concatenação dos nomes de todos os componentes no caminho entre o componente atual e o componente procurado. Assim, por exemplo, $component->lookupPath(Nette\Application\UI\Presenter::class) retorna um identificador único do componente em relação ao presenter.

Container

Nette\ComponentModel\Container é o componente pai, ou seja, um componente que contém descendentes e forma assim uma estrutura em árvore. Possui métodos para fácil adição, obtenção e remoção de objetos. É o ancestral, por exemplo, do formulário ou das classes Control e Presenter.

getComponent(string $name): ?Component

Retorna um componente. Ao tentar obter um descendente indefinido, a fábrica createComponent($name) é chamada. O método createComponent($name) chama o método createComponent<nome do componente> no componente atual e passa o nome do componente como parâmetro. O componente criado é então adicionado ao componente atual como seu descendente. Chamamos esses métodos de fábricas de componentes e eles podem ser implementados por descendentes da classe Container.

getComponents(): array

Retorna os descendentes diretos como um array. As chaves contêm os nomes desses componentes. Nota: na versão 3.0.x, o método retornava um iterador em vez de um array, e seu primeiro parâmetro determinava se os componentes deveriam ser percorridos em profundidade, e o segundo representava um filtro de tipo. Esses parâmetros estão obsoletos.

getComponentTree(): array

Obtém toda a hierarquia de componentes, incluindo todos os componentes filhos aninhados, como um array indexado. A busca é feita primeiro em profundidade.

Monitoramento de Ancestrais

O modelo de componente Nette permite um trabalho muito dinâmico com a árvore (podemos remover, mover, adicionar componentes), portanto seria um erro confiar que, após a criação de um componente, o pai, o pai do pai, etc., sejam imediatamente conhecidos (no construtor). Na maioria das vezes, o pai não é conhecido durante a criação.

Como saber quando um componente foi anexado à árvore do presenter? Observar a mudança do pai não é suficiente, porque o pai do pai pode ter sido anexado ao presenter, por exemplo. O método monitor($type, $attached, $detached) ajuda. Cada componente pode monitorar qualquer número de classes e interfaces. A anexação ou desanexação é sinalizada chamando o callback $attached ou $detached, respectivamente, e passando o objeto da classe monitorada.

Para melhor compreensão, um exemplo: a classe UploadControl, que representa o elemento de formulário para upload de arquivos no Nette Forms, precisa definir o atributo enctype do formulário para o valor multipart/form-data. No entanto, no momento da criação do objeto, ele pode não estar anexado a nenhum formulário. Em que momento, então, modificar o formulário? A solução é simple – no construtor, solicita-se o monitoramento:

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 assim que o formulário estiver disponível, o callback é chamado. (Anteriormente, os métodos comuns attached e detached eram usados em seu lugar).