Modelo do componente
Um conceito importante em Nette é o componente. Inserimos componentes visuais interativos em páginas, formulários ou todos os
seus elementos são também componentes. Há duas classes básicas das quais todos esses componentes herdam, fazem parte do pacote
nette/component-model
e são responsáveis pela criação da hierarquia da árvore de componentes.
Component
Nette\ComponentModel\Component
é o ancestral comum de todos os componentes. Ele contém o método getName()
devolvendo o nome do componente e
o método getParent()
devolvendo seu pai. Ambos podem ser definidos com o método setParent()
–
o primeiro parâmetro é o pai e o segundo é o nome do componente.
lookup (string $type): ?Component
Procura na hierarquia por um objeto da classe ou interface desejada. Por exemplo,
$component->lookup(Nette\Application\UI\Presenter::class)
retorna apresentador se o componente estiver conectado
a ele, apesar de vários níveis.
lookupPath (string $type): ?string
Retorna o chamado caminho, que é uma cadeia formada por concatenar os nomes de todos os componentes no caminho entre
o componente atual e o componente que está sendo procurado. Assim, por exemplo,
$component->lookupPath(Nette\Application\UI\Presenter::class)
retorna o identificador único do componente em
relação ao apresentador.
Container
Nette\ComponentModel\Container
é o componente pai, ou seja, o componente que contém as crianças e assim formando a estrutura em árvore. Possui métodos
para facilmente adicionar, recuperar e remover componentes. É o ancestral, por exemplo, da forma ou classes Control
e Presenter
.
getComponent (string $name): ?Component
Devolve um componente. Tentativa de chamar de criança indefinida causa invocação de fábrica criarComponente($nome).
Método createComponent($name)
invoca método createComponent<component name>
no componente atual
e ele passa o nome do componente como parâmetro. O componente criado é então passado para o componente atual como seu filho.
Chamamos essas fábricas de componentes, elas podem ser implementadas em classes herdadas de Container
.
getComponents(): array
Retorna os descendentes diretos como uma matriz. As chaves contêm os nomes desses componentes. Observação: na versão 3.0.x, o método retornava um iterador em vez de uma matriz, e seu primeiro parâmetro especificava se deveria iterar pelos componentes em profundidade, e o segundo representava um filtro de tipo. Esses parâmetros estão obsoletos.
getComponentTree(): array
Retorna toda a hierarquia de componentes, inclusive todos os componentes filhos aninhados, como uma matriz indexada. A pesquisa é feita primeiro em profundidade.
Monitoramento de Ancestrais
O modelo de componentes Nette permite um trabalho em árvore muito dinâmico (podemos remover, mover, adicionar componentes), portanto seria um erro confiar no fato de que, depois de criar um componente, o pai, o pai da mãe, etc. são conhecidos imediatamente (no construtor). Normalmente, o pai não é conhecido de forma alguma quando o componente é criado.
Como descobrir quando um componente foi adicionado à árvore apresentadora? Não basta acompanhar a mudança dos pais, porque
os pais dos pais poderiam ter sido anexados ao apresentador, por exemplo. O método do monitor ($type, $attached,
$detached) pode ajudar. Cada componente pode monitorar qualquer número de classes e interfaces. A conexão ou desconexão é
anunciada ligando para $attached
e $detached
, respectivamente, e passando o objeto da classe
monitorada.
Um exemplo: A classe UploadControl
, que representa o elemento do formulário para carregar arquivos nos
Formulários Nette, tem que definir o atributo do formulário enctype
para valorizar
multipart/form-data
. Mas no momento da criação do objeto, ele não precisa ser anexado a nenhum formulário. Quando
modificar o formulário? A solução é simples – nós criamos um pedido de monitoramento no construtor:
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 o formulário está disponível, a ligação de retorno é chamada. (Anteriormente, os métodos comuns
attached
e detached
eram usados em seu lugar).