Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - Building form based on user input

I'm building a web form that is supposed to be dynamic.
When a user selects an option from a list, the next form inputs are generated based on his input.
For instance:

<mat-form-field>
     <mat-select placeholder="Type" [(ngModel)]="row.Type" (change)="TypeChosen(row.Type, row)">
         <mat-option [value]="0">Treatment</mat-option>
         <mat-option [value]="1">Travel</mat-option>
         <mat-option [value]="2">Medication</mat-option>
         <mat-option [value]="3">Equipment</mat-option>
     </mat-select>
</mat-form-field>

If he selects Type 'Treatment', he gets another selection input with some options with a few other inputs, and if he selects a different Type, he gets different options and other inputs.

I understand that I need to dynamically generate HTML content, and maybe a dynamic component.
What is the best approach to do this in an easy way?

like image 404
amitairos Avatar asked Jun 13 '18 08:06

amitairos


People also ask

What are the ways to build forms in Angular?

You can build forms by using Angular template syntax and directives to write templates with the form-specific directives. This tutorial describes the directives and techniques to use when writing templates. You can also use a reactive or model-driven approach to build forms.

What is NgForm Angular?

NgForm is used to create a top-level form group Instance, and it binds the form to the given form value.

What is dynamic form in Angular?

A dynamic form requires an object model that can describe all scenarios needed by the form functionality. The example hero-application form is a set of questions —that is, each control in the form must ask a question and accept an answer. The data model for this type of form must represent a question.


2 Answers

I'd suggest creating a component for each sub-form and then *ngIf them based on the selected option, like so:

<!-- component.html -->

<mat-form-field>
  <mat-select placeholder="Type" [(ngModel)]="row.Type" (change)="onTypeChosen(row.Type, row)">
    <mat-option [value]="0">Treatment</mat-option>
    <mat-option [value]="1">Travel</mat-option>
    <mat-option [value]="2">Medication</mat-option>
    <mat-option [value]="3">Equipment</mat-option>
  </mat-select>
</mat-form-field>

<my-treatment-component *ngIf="type === 0" [someInput]="'some value'"></my-treatment-component>
<my-travel-component *ngIf="type === 1" [somethingElse]="true"></my-travel-component>
<my-medication-component *ngIf="type === 2" (someOutput)="onMedicationOutput($event)"></my-medication-component>
<my-equipment-component *ngIf="type === 3"></my-equipment-component>

If you already have something holding your Type selection, you can bind that to the *ngIfs instead. If not, create a field in your controller class and hold the selected type in there.

// component.ts

public type: number | null = null;

public onTypeChosen(type: number, row): void {
  this.type = type;
}

If your sub-forms have parts that are re-usable (or are basically the same, sans configuration), it's generally a good practice to extract the re-usable code into components in and of themselves and compose them together.

Hope this helps a little :-)

like image 72
Heehaaw Avatar answered Sep 17 '22 15:09

Heehaaw


To Add the options dynamically, angular provide ( *ngFor ).

<mat-form-field>
     <mat-select placeholder="Type" [(ngModel)]="row.Type" (change)="TypeChosen(row.Type, row)" *ngFor="let option of options; let i = index">
         <mat-option (click)="updateOptions(option)" [value]="{{i}}">option.text</mat-option>
     </mat-select>
</mat-form-field> 

in your controller .ts

private options = [];

private initOptions(){
this.options = [
{text:'Treatment' , possibleOptionsRelates:[text:'possible1']},
{text:'Travel' , possibleOptionsRelates:[text:'possible12']},
{text:'Medication' , possibleOptionsRelates:[text:'possible13']}];
}
private updateOptions(option){
     this.options.push(...option.possibleOptionsRelates);
}
like image 32
Bassam Avatar answered Sep 16 '22 15:09

Bassam