Formulario dinámico en Angular

Hola buenas a todos! espero que estén bien, hoy vamos a ver un tema que estuve trabajando estas semanas, como investigación para un proyecto personal, y es el uso de Formulario Dinámico con Angular.

En este caso el problema era que el usuario necesita crear productos, pero no todos los productos tenían los mismos atributos, algunos tenían mas otros menos. En este caso el usuario quería configurar sus propios campos, y decidir si son requeridos o no, o si es dropbox o no, etc.

Siguiendo un ejemplo básico de la pagina de Angular, logramos algo asi:

Para cargar elementos al formulario dinamo seguimos lo siguiente:

Y al guardarlo queda de la siguiente manera.

Si agregamos mas campos quedaría de la siguiente manera:

Ahora en otra pantalla, donde vamos a hacer uso del formulario dinamico, podemos ver algo como lo siguiente:

y luego al elegir el formulario podremos ver como se crean los campos dinamicamente.

Como pueden ver, visualmente queda muy bien y ordenado ahora veremos un poco el código usado:

Aquí las interfaces que vamos a usar:

 

export interface IDynamicForm {
  form_id?: number;
  form_description?: string;
  country?: string;
  value?: string;
  key?: string;
  label?: string;
  labelEs?: string;
  labelEn?: string;
  labelBr?: string;
  info?: string;
  infoEs?: string;
  infoEn?: string;
  infoBr?: string;
  required?: any;
  order?: number;
  type?: string;
  options?: Option[];
  environment?: string;
  domain?: string;
  customer_domain?: string;
  session_id?: string;
  api_id?: string;
  control_type?: string;
  comparable?: boolean;
  graphic?: boolean;
  icon?: string;
}

Ahora vemos el formgroup que vamos a usar

editForm = this.fb.group({
    form_id: [null, [Validators.required]],
    value: [null, [Validators.required]],
    keyForm: [null, [Validators.required]],
    labelForm: [null, [Validators.required]],
    requiredForm: [null, [Validators.required]],
    order: [null, [Validators.required]],
    control_type: [null, [Validators.required]],
    type: [],
    options: [],
    keyOption: [],
    valueOtion: [],
  });

Aqui el metodo que corresponde al boton de Guardar:

 
private createFromForm(): IDynamicForm {
    return {
      ...new DynamicForm(),
      form_id: this.editForm.get([ 'form_id' ])!.value,
      value: this.editForm.get(['value'])!.value,
      key: this.editForm.get(['keyForm'])!.value,
      label: this.editForm.get(['labelForm'])!.value,
      required: this.editForm.get(['requiredForm'])!.value,
      order: this.editForm.get(['order'])!.value,
      control_type: this.editForm.get(['control_type'])!.value,
      type: this.editForm.get(['type'])!.value,
      options: this.editForm.get(['options'])!.value,
    };
  }

Ya teniendo el “DynamicForm” procedemos a enviarlo a nuestro BackEnd y listo la primera parte.

Mostrar campos del Formulario.

Ahora veremos un poco como seria el código para mostrar los campos del formulario dinámico en la pantalla que la necesitemos:

Nuestro HTML quedaria de la siguiente forma:

 
<div [formGroup]="form">
  <mat-form-field appearance="outline" style="width: 100%;">
    <mat-label [attr.for]="solicitud.key">{{ solicitud.label }}</mat-label>

    <div [ngSwitch]="solicitud.control_type">
      <input matInput *ngSwitchCase="'textbox'" [formControlName]="solicitud.key" [id]="solicitud.key" [type]="solicitud.type" />

      <mat-select [id]="solicitud.key" *ngSwitchCase="'dropdown'" [formControlName]="solicitud.key">
        <mat-option *ngFor="let opt of solicitud.options" [value]="opt.key">{{ opt.value }}</mat-option>
      </mat-select>
    </div>
    <mat-error class="errorMessage" *ngIf="!isValid"><span jhiTranslate="entity.validation.required"> is required</span></mat-error>
  </mat-form-field>
</div>

Nuestro Componente quedaria de la siguiente manera:

 
@Component({
  selector: 'app-formulario',
  templateUrl: './solicitud-formulario.component.html',
  styleUrls: ['./solicitud-formulario.component.scss'],
})
export class FormularioComponent implements OnInit {
  @Input() solicitud: IDynamicForm;
  @Input() form: FormGroup;
  @Input() disabled: boolean;

  constructor() {}

  ngOnInit(): void {}

  get isValid(): boolean {
    if (this.form.controls[this.solicitud.key]) {
      return this.form.controls[this.solicitud.key].valid;
    } else {
      return false;
    }
  }
}

Ahora lo que nos queda hacer es obtener el formulario, recorrerlo y mostrarlo en el HTML, puede ser algo como lo siguiente:

 
<form [formGroup]="formList">
            <mat-tab-group>
              <mat-tab *ngFor="let item of itemsFormDyn" label="{{ item.formId }}">
                <div class="tab-content p-24" fusePerfectScrollbar>
                  <mat-grid-list [cols]="breakpoint3" rowHeight="9rem" (window:resize)="onResize($event)">
                    <!--              <div *ngFor="let solicitud of solicitudes" class="form-row" >-->
                    <mat-grid-tile *ngFor="let solicitud of item.itemSol">
                      <app-formu
                        [solicitud]="solicitud"
                        [form]="formList"
                        class="input-full-width"
                      ></app-formu>
                    </mat-grid-tile>
                  </mat-grid-list>
                </div>
              </mat-tab>
            </mat-tab-group>
</form>
 

 

Todo eso nos dara el resultado que vimos anteriormente:

Bueno espero les sea de utilidad, desde ya muchas gracias por visitar mi blog. Saludos a todos.

3 COMMENTS
  • By David Gonzales

    Se ve excepcionalmente bien, tienes codigo en github?

    / Responder
    • By jlopezjujuy

      Hola David, si, pero es un repo privado. solo pude compartir algunas cosas. No puedo compartir otras cosas mas.

      / Responder
  • By David Gonzales

    entiendo, gracias.

    / Responder

LEAVE YOUR COMMENTS