angulartypescriptangular-reactive-formsangular-formsangular-dynamic-forms

Getting form's input type from TypeScript


I am defining the type of my form's fields in the ts, like following:

 myFormFields = [{
     label: 'Active',
     formControlName: 'active',
     value: false,
     type: 'checkbox'       
}]

Then in the html I'm trying to show them, like following:

 <div class="form-floating mb-3">
   <input type="{{field.type}}" formControlName="{{field.formControlName}}" />
   <label class="form-label">
      {{field.label}}
   </label> 
 </div>  

                  

The problem is that, if I define the type of the input by type="{{field.type}}" its value is not considered, i.e., it is never checked! But if I use type="checkbox", then it is checked when the value is true and non-checked if it is false.

I checked the Inspect, the only difference I could see was that, when input type is defined by field.type it has value property, like :

//(checkbox is not checked.)
<input _ngcontent-ng-c3053247743="" type="checkbox" ng-reflect-name="active"
ng-reflect-ng-class="[object Object]" value="true" class="ng-untouched ng-pristine ng-valid">

but when it is set to type='checkbox' it does not have any value property:

//(checkbox is checked.)
<input _ngcontent-ng-c2417600516="" type="checkbox" ng-reflect-name="active"
ng-reflect-ng-class="[object Object]" class="ng-untouched ng-pristine ng-valid">

Does anyone know what is the problem? Thank you in advance.


Solution

  • The reason what you are trying won't work is because input[type=checkbox] is part of the selector for the directive CheckboxControlValueAccessor. By trying making the type attribute dynamic, you are preventing the directive from being used, since directive selectors are found at compile time and therefore only work with static values.

    One way to accomplish what you're trying to do is with a @switch block where every expected input type is handled.

    @switch(file.type) {
      @case('checkbox') {
        <input type="checkbox" [formControlName]="field.formControlName" />
      }
      @default {
        <input type="text" [formControlName]="field.formControlName" />
      }
    }