Show hide text box when specific option is selected from dropdown inside dynamic form Angular

Viewed 1994

I have a form where a user could add one/more div of Address on click of add button.

I want if user select options=5 from the dropdown, want to show and hide textbox in that particular address Div.

Component Code

        get contactFormGroup() {
            return this.form.get('Array') as FormArray;
          }

          ngOnInit() {
            this.form= this.fb.group({
              Array: this.fb.array([])
            });
          }

          createContact(): FormGroup {
            return this.fb.group({
              ABC: [null, Validators.compose([Validators.required])],
              Test: [null, Validators.compose([Validators.required])]
            });
          }

          addContact() {
            this.Group.push(this.createContact());
          }

          showValue(event) {
            const selectedValue = event;
            if (selectedValue === '5') {
                this.showValuetxtbox = true;
            } else {
                this.showValuetxtbox = false;
            }
          }
2 Answers

As you are looping to add the divs, you could use a template reference variable on the drop down. e.g #select then refer to that in the *ngIf:

    <form [formGroup]="addExpressionform">
        <div formArrayName="expressionArray">
            <div *ngFor="let item of contactFormGroup.controls; let i = index;" [formGroupName]="i">

              <carbon-dropdown #select
                                (optionSelected)="showValue($event)"
                                [formControlN]="'UOM'"
                                [options]="listOptions" [formGroup]="item"
                                name="UOM" 
                                >
                            </carbon-dropdown>

                            <carbon-text-input *ngIf="select.value == 5" 
                                [formControlN]="'Value'"
                                [formGroup]="item"
                                name="Value"
                                >
                            </carbon-text-input>
                    <carbon-button type="primary" (click)="submit()" id="save-parameter">Save</carbon-button>

            </div>                  
        </div>
    </form>

Simplified StackBlitz demo.

Take a look at this Stackblitz, it's referred to in the Angular docs and could serve as boilerplate to what you are trying to achieve.

You should isolate every possible type of question by creating a different class for each one, so you can shape the data and then use ngSwitch to dynamically create the HTML accordingly.

Question base class:

export class QuestionBase<T> {
  controlType: string;
  value: T;
  key: string;
  label: string;
  // etc

  constructor(options) {
    // constructor logic
  }
}

Some special class that inherents from base class

import { QuestionBase } from './question-base';

export class SpecialQuestion extends QuestionBase<string> {
  controlType = 'specialQuestion';
  type: string;

  // special Question
  specialValue: string;


  constructor(options) {
    super(options);
    this.type = options['type'] || '';
  }
}

Then, a question component:

<div [formGroup]="form">
  <label>{{question.label}}</label>        
  <div [ngSwitch]="question.controlType">
    // controls logic
    <input *ngSwitchCase="'textbox'" >        
    <select *ngSwitchCase="'specialQuestion'"></select>
  </div>          
</div>

Then you throw this into a container component where you loop through the entire questions array.

This way your code will be future proof and reusable as you add/change functionality to your forms down the road. You won't have to create spaghetti to meet edge case requirements like an extra input field.

Related