Вам необходимо реализовать ControlValueAccessors в общем компоненте, чтобы вы могли присоединять к ним formControls в родительском компоненте. Вот отличная статья о том, что это очень мило.
https://medium.com/@majdasab/implementing-control-value-accessor-in-angular-1b89f2f84ebf
Вот как должен выглядеть ваш компонент customDropdown для реализации ControlValueAccessors
import { OnInit } from '@angular/core';
import { Component, forwardRef, HostBinding, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-common-dropdown',
templateUrl: './common-dropdown.component.html',
styleUrls: ['./common-dropdown.component.css'],
providers: [
{ provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CommonDropdownComponent),
multi: true
}
]
})
export class CommonDropdownComponent implements ControlValueAccessor {
@Input() placeHolder: string;
@Input() dropDownId: string;
@Input() dataList: any;
onChange: any = () => {}
onTouch: any = () => {}
val= "" // this is the updated value that the class accesses
set value(val){ // this value is updated by programmatic changes if( val !== undefined && this.val !== val){
this.val = val
this.onChange(val)
this.onTouch(val)
}
constructor() { }
ngOnInit() {
}
// this method sets the value programmatically
writeValue(value: any){
this.value = value
}
registerOnChange(fn: any){
this.onChange = fn
}
registerOnTouched(fn){
this.onTouch = fn
}
propagateChange(_){
}
selectClicked(event: any) {
const ele = event.srcElement.parentNode;
ele.classList.toggle('cs-active');
}
selectedOption(ctrl: string, value: string) {
this.onChange(value) // <-- CRUCIAL need to inform formControl to update the value
document.getElementById(ctrl).innerHTML = value;
const ele = document.getElementById(ctrl).parentElement;
ele.classList.toggle('cs-active');
}
closeDropDown(event: any) {
const ele = event.srcElement;
ele.classList.remove('cs-active');
}
}
Теперь, когда мы добавили возможность прикреплять formControls к вашему пользовательскому компоненту, вы можете добавить их в html в вашем app.component:
<form [formGroup]="parentForm">
<app-common-dropdown placeHolder="select district" [dropDownId]="'districtLabel'" [dataList]="['bangalore','chennai','pune']" formControlName="district" ></app-common-dropdown>
<app-common-dropdown placeHolder="select distance" [dropDownId]="'distanceLabel'" [dataList]="[100,200,300,400]" formControlName="distance" ></app-common-dropdown>
<app-common-dropdown placeHolder="select state" [dropDownId]="'stateLabel'" [dataList]="['karnataka','tamil nadu','mumbai']" formControlName="state" ></app-common-dropdown>
</form>
<button type="submit" (click)="getFormValues()">submit</button>
И вам нужно будет настроить имена в вашей группе форм, поскольку они не соответствуют HTML-форме
this.parentForm = this.fb.group({
district: ['bangalore', Validators.required], <--- SETS THE DEFAULT VALUE OF THE FORM CONTROL
distance: [''],
state:['']
});
formControlName должен соответствовать свойству внутри parentForm.