typescript - Angular 2 criando formulários reativos com componentes aninhados
Minha exigência é que eu preciso criar um formulário com componentes aninhados. Estou criando componentes para cada campo do formulário, ou seja, para a caixa de texto haverá um componente, para o botão de opção haverá outro componente da mesma forma.
<form [formGroup]="myForm">
<textbox-component></textbox-component>
<radioButton-component></radioButton-component>
</form>
E eu quero usar formulários reativos para criar este formulário, pois quero que meu HTML permaneça intacto e que minhas validações de formulário sejam feitas apenas através do TypeScript.
Mas eu não consigo encontrar nenhuma solução de como podemos ter formulários reativos aninhados com componentes.
Resposta #1
Após minhas pesquisas e experimentos, encontrei uma resposta para minha pergunta, então estou respondendo por mim mesmo. Se isso poupar tempo de alguém, ficarei feliz.
Se você quiser criar formulários reativos com componentes aninhados, você pode fazer como abaixo
Aqui estou criando um formulário com dois componentes aninhados, um para caixa de texto e outro para botão de rádio
Seu componente pai pode ser assim
<form [formGroup]="myForm">
<child-textbox-component [parentFormGroup]="myForm">
</child-textbox-component>
<child-radio-button-component [parentFormGroup]="myForm">
</child-radio-button-component>
</form>
Estamos passando o objeto FormGroup como entrada para componentes filhos, que foi criado no componente pai como entrada para os componentes filhos; eles usarão este objeto FormGroup em seu componente para projetar o controle específico da classe
Seus componentes filhos serão assim
componente-caixa-de-texto-filho
<div class="form-group" [formGroup]="parentFormGroup">
<label>
{{control.caption}}
</label>
<input class="form-control" type="text" [title]="control.toolTip"
[attr.maxlength]="control.width" [name]="control.name"
[value]="control.defaultValue" [formControlName]="control.name"/>
</div>
componente-de-botão-de-radio-filho
<div class="form-group" [formGroup]="parentFormGroup">
<label>
{{control.caption}}
</label>
<div>
<label *ngFor="let value of control.values; let idx = index"
class="radio-inline" [title]="control.tooltip">
<input type="radio" [name]="control.name" [formControlName]="control.name"/>
{{ value }}
</label>
</div>
</div>
Aqui, control é a classe de modelo que detém os dados a serem exibidos para esses componentes filhos.
Dessa forma, você pode ter seu formulário gerado usando componentes aninhados, de modo que você não precise ter seu formulário (pode-se dizer um formulário grande) em um único componente. Você pode dividi-lo em quantos subcomponentes quiser e o formulário será fácil de criar e manter também usando formulários reativos do Angular 2. Você também pode adicionar facilmente validações.
Eu segui esses links antes de responder isso
algo semelhante no stackoverflow
formulários dinâmicos do Angular 2
Resposta #2
Nota adicional à resposta de Mhesh, você pode construir essa mesma solução sem injetar [parentFormGroup] no HTML. Você pode fazer isso seguindo este post do Stack Overflow sobre grupos de formulário reutilizáveis.
Isto é realmente bom.
Exemplo
Para usar a solução existente, você pode fazer a mesma coisa, exceto:
Seu componente pai pode ser assim, sem nenhum parâmetro adicional passado
<form [formGroup]="myForm">
<child-textbox-component></child-textbox-component>
<child-radio-button-component></child-radio-button-component>
</form>
Observe também que você pode definir grupos de formulários assim:
<form [formGroup]="myForm">
<child-textbox-component></child-textbox-component>
<child-radio-button-component formGroupName="myGroup"></child-radio-button-component>
</form>
componente-caixa-de-texto-filho
<div class="form-group" [formGroup]="controlContainer.control">
<label>
{{control.caption}}
</label>
<input class="form-control" type="text" [title]="control.toolTip"
[attr.maxlength]="control.width" [name]="control.name"
[value]="control.defaultValue" [formControlName]="control.name"/>
</div>
Para habilitar isso, você deseja injetar um ControlContainer no seu @Component
@Component({
moduleId: `MODULE_ID_HERE`,
selector: "child-textbox-component",
templateUrl: "childTextbox.component.html",
})
export class ChildTextboxComponent {
constructor(private controlContainer: ControlContainer, OTHER_PARAMETERS) {
}
}
