Custom input component

Asked

Viewed 552 times

2

Hello, I have a form 'Reactive Forms' where it has several fields, (several inputs), so I decided to create a Component and run an ngFor on it to reduce the number of lines...

Component html

<div *ngFor='let input of inputs' class="input-size-{{input.size}}" >
    <label>{{input.label}}</label>

    <input *ngIf='input.control == "input"' class="{{input.css}}" type="{{input.type}}" />

    <textarea *ngIf='input.control == "textarea"' class="{{input.css}}"></textarea>

    <select *ngIf='input.control == "select"' class="{{input.css}}">
        <option value="">:: Selecione ::</option>
    </select>
</div>

Component TS

/* Angular */
import { Component, Input} from "@angular/core";
import { FormularioModel } from "./vw.formulario.model";

@Component({
    selector: 'vw-input',
    templateUrl: './vw.input.html',
    styleUrls: ['./vw.input.scss']
})

export class VwInput{   
    @Input() inputs: FormularioModel[];
}

Component Model

export class FormularioModel {
    constructor(
        public control: string, 
        public label: string, 
        public value: any, 
        public formControlName: string, 
        public css: string, 
        public type: string, 
        public size: number){
    }
}

And I implement this Component as follows...

Html form

<form [formGroup]='formulario' novalidate>
    <!-- Inputs gerados -->
    <!-- IMPLEMENTAÇÃO DO COMPONENT DE INPUT -->
    <vw-input [inputs]='inputs' ></vw-input>

    <!-- Footer -->
    <vw-formulario-footer></vw-formulario-footer>

    <div class="container-button">
        <button>Enviar</button>
    </div>
</form>

Formulario TS

/* Angular */
import { Component } from "@angular/core";
import { FormGroup, FormBuilder, Validators, AbstractControl, NgControlStatus, FormControl } from '@angular/forms';


import { FormularioModel } from "../../vw.shared/vw.input/vw.formulario.model";

@Component({
    selector: 'vw-formulario',
    templateUrl: './vw.formulario.html',
    styleUrls: ['vw.formulario.scss']
})

export class VwFormulario {

    formulario: FormGroup;
    caracteres_restantes: number;

    inputs: FormularioModel[] = [
        {control:'select', label: 'Motivo', value: '', formControlName: 'motivo', css: 'vw-input', type: 'text', size: 6},
        {control:'select', label: 'Assunto', value: '', formControlName: 'assunto', css: 'vw-input', type: 'text', size: 6},
        {control:'input', label: 'E-mail', value: '', formControlName: 'email', css: 'vw-input', type: 'text', size: 6},
        {control:'input', label: 'Nome', value: '', formControlName: 'nome', css: 'vw-input', type: 'text', size: 6},
        {control:'input', label: 'CPF', value: '', formControlName: 'cpf', css: 'vw-input', type: 'text', size: 6},
        {control:'input', label: 'Data Nascimento', value: '', formControlName: 'dt_nascimento', css: 'vw-input', type: 'text', size: 2},
        {control:'input', label: 'DDD', value: '', formControlName: 'ddd', css: 'vw-input', type: 'text', size: 1},
        {control:'input', label: 'Telefone', value: '', formControlName: 'telefone', css: 'vw-input', type: 'text', size: 3},
        {control:'input', label: 'Endereco', value: '', formControlName: 'endereco', css: 'vw-input', type: 'text', size: 6},
        {control:'input', label: 'Número', value: '', formControlName: 'numero', css: 'vw-input', type: 'text', size: 2},
        {control:'input', label: 'Complemento', value: '', formControlName: 'complemento', css: 'vw-input', type: 'text', size: 2},
        {control:'input', label: 'CEP', value: '', formControlName: 'cep', css: 'vw-input', type: 'text', size: 2},
        {control:'select', label: 'Estado', value: '', formControlName: 'estado', css: 'vw-input', type: 'text', size: 6},
        {control:'select', label: 'Cidade', value: '', formControlName: 'cidade', css: 'vw-input', type: 'text', size: 6},
        {control:'input', label: 'Bairro', value: '', formControlName: 'bairro', css: 'vw-input', type: 'text', size: 6},
        {control:'textarea', label: 'Mensagem', value: '', formControlName: 'mensagem', css: 'vw-input', type: 'text', size: 12}
    ]


    constructor(fb: FormBuilder){
        /* Grupo de formulario - Validações */
        this.formulario = fb.group({
            motivo: new FormControl('', [ Validators.required ]),
            assunto: new FormControl('', [ Validators.required ]),
            email: new FormControl('', [ Validators.required ]),
            nome: new FormControl('', [ Validators.required ]),
            cpf: new FormControl('', [ Validators.required ]),
            dt_nascimento: new FormControl('', [  ]),
            ddd: new FormControl('', [ Validators.required ]),
            telefone: new FormControl('', [ Validators.required ]),
            endereco: new FormControl('', [ Validators.required ]),
            numero: new FormControl('', [ Validators.required ]),
            complemento: new FormControl('', [  ]),
            cep: new FormControl('', [ Validators.required ]),
            estado: new FormControl('', [ Validators.required ]),
            cidade: new FormControl('', [ Validators.required ]),
            bairro: new FormControl('', [ Validators.required ]),
            mensagem: new FormControl('', [ Validators.required ]),
        });
    }
}

However, my formGroup is not associating with the inputs generated by Component. I would like to know how I make this bridge to get the values of each input and perform the validation by formGroup!

Thank you in advance....

2 answers

0


Assign formControlName in each input, which was being passed only in the model and not applied in the Input. The input was as follows...

<input *ngIf='input.control == "input"' formControlName='{{input.formControlName}}' class="{{input.css}}" type="{{input.type}}" />

In addition, I passed my formGroup as input Component parameter to as follows:

<vw-input [formGroup]="formulario" [inputs]='inputs' ></vw-input>

Receiving the same in the Component TS as follows:

@Input() formGroup: FormGroup;

And assigning it to one as follows:

<div [formGroup]="formGroup">
    <div *ngFor='let input of inputs' class="input-size-{{input.size}}" >
        <label>{{input.label}}</label>
        
        <input *ngIf='input.control == "input"' formControlName='{{input.formControlName}}' class="{{input.css}}" type="{{input.type}}" />
    </div>
</div>

Thus obtaining the desired result...

0

Failed to inform formControlName.

<input *ngIf='input.control == "input"' class="{{input.css}}" type="{{input.type}}" formControlName='{{ input.formControlName }}' />
  • In addition, it is necessary to follow the steps of the answer below.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.