Dividindo formulários complexos no Angular com ControlContainer
Desenvolver formulários complexos é uma das tarefas mais desafiadoras no Front-end, principalmente quando precisamos lidar com muitas validações e reaproveitamento de componentes. No Angular temos os Reactive Forms que disponibilizam várias ferramentas para lidar com essas situações, e dentro deste pacote temos o ControlContainer, uma classe que ajuda a gerenciar melhor nossos formulários.
Formulários aninhados e componentes filhos
Um exemplo clássico do seu uso é quando temos um formulário com muitos controles e eles podem ser reutilizados em outros lugares. Cadastros de pessoas irão pedir dados em comum como nome, sobrenome e data de nascimento. E eles podem vir de cadastros distintos como por exemplo clientes e fornecedores.
Seria legal ter um componente com todos esses dados em comum para podermos utilizar em vários formulários. Mas como vamos fazer isso sendo que a declaração do FormGroup estará dentro do componente pai?
Injetando o ControlContainer
A classe ControlContainer fará brilhantemente esse papel. Ao injetá-lo em um componente filho, recuperamos a instância do FormGroup do componente pai. Podemos então criar um componente que possui o template dos controles do cadastro de pessoas e reutilizá-lo nos componentes de clientes e fornecedores.
Agora basta chamar o componente filho nos componentes pais:
Utilização em diretivas
Agora veremos um cenário onde precisamos adicionar mais dois campos no formulário do fornecedor. Um checkbox para informar se o fornecedor possui CNH e um input para informar o número da CNH. Este input só será obrigatório se o checkbox estiver marcado. Se o checkbox estiver desmarcado então o input ficará desabilitado.
Pensando que esta regra poderá se repetir para outros campos, podemos criar uma diretiva reutilizável injetando o ControlContainer.
Veja que interessante a dinâmica desta diretiva. Primeiramente capturamos os nomes dos controles que nos interessam por Input (Neste caso é o checkbox e o campo da CNH).
Como sabemos que temos a referência do formulário com o ControlContainer, podemos então ouvir as mudanças de valor do nosso checkbox com o observable valueChanges. Dentro do subscribe basta fazer a condição: Se estiver checado habilitamos o input, caso contrário desabilitamos o input e de quebra limpamos o seu valor.
No template HTML do componente chamamos a diretiva dentro do controle.
O seletor da diretiva recebe o nome do controle que vamos ouvir as mudanças (checkbox hasCnh). Já o controle que será alterado (cnh) é capturado pelo seletor formControlName. Simples e reutilizável!
Você pode conferir os exemplos deste artigo pelo StackBlitz:
Conclusão
Temos infinitas possibilidades na construção de formulários complexos e reativos utilizando o ControlContainer. Com ele podemos facilmente dividir os formulários em várias camadas e separar responsabilidades em outros componentes e diretivas.