I have angular reusable select component that accepts formControlName
as @Input
. and renders select component and options are passed as child component and rendered inside <ng-content>
.
select.component.ts
import {Component, forwardRef, Input, OnInit} from '@angular/core';
import {FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
import {faChevronDown} from '@fortawesome/pro-solid-svg-icons';
@Component({
selector: 'component-select',
templateUrl: './select.component.html',
styleUrls: ['./select.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => SelectComponent),
}
]
})
export class SelectComponent implements OnInit {
@Input() formControlName: string;
public formControl: FormControl = new FormControl();
public onChange: (_: any) => void = () => {};
public onTouched: () => void = () => {}
constructor() {
}
ngOnInit(): void {
}
writeValue(obj: any): void {
this.formControl.setValue(obj);
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(disabled: boolean): void {
disabled ? this.formControl.disable() : this.formControl.enable();
}
protected readonly faChevronDown = faChevronDown;
}
select.component.html
<component-label><ng-content select="[slot=label]"></ng-content></component-label>
<div class="input-container">
<div class="left-icon"> <ng-content select="[slot=left-icon]"></ng-content></div>
<select class="form-input highlight-on-error" [formControl]="formControl" (change)="onChange(formControl.value)" >
<ng-content></ng-content>
</select>
<div class="right-icon"><fa-icon [icon]="faChevronDown"></fa-icon></div>
</div>
<component-error-message [controlName]="formControlName"></component-error-message>
Usage of this component is simple, it will receive form control from FormGroup as formControlName, in some cases form control will have default value setted. In that case writeValue
will receive obj as param and it is correctly passed, but setValue
won’t be called and select have empty value.
Usage
this.formBuilder.group({
nationality: [this.entry?.nationality === '' ? null : this.entry?.nationality]
});
<component-select formControlName="nationality">
<ng-container slot="label">{{ 'STEP_KYC_FORM__NATIONALITY_LABEL' | translate }}</ng-container>
<option [ngValue]="null"></option>
<option [ngValue]="option.code" *ngFor="let option of countries$ | async">{{ option.name }}</option>
</component-select>
Problem is if entry has nationality, then it should set the value. Currently it is not setted. Which part of the select component logic should I change to set the value if value is loaded before initialization of component ?