问题
I do have a custom component for template driven form where I use NG_VALUE_ACCESSOR. It works really good. Now I would like to switch to reactive form. StackBlitz Demo
The issue is that how to use a reactive form as a custom component and pass
formGroup and formControlName and also how to pass the rest of the other attributes dynamically to the parent component such as required etc.
The required attribute as fare as I know, is being defined in the *.component.ts file. Therefore it would not be possible to set dynamically in the parent as an attribute binding like in template driven form.
I have been searching but unfortunately no significant result.
Any Idea how could I implement reactive form as custom component using NG_VALUE_ACCESSOR and passing attribute dynamically?
回答1:
Really I don't know what do you want. Your custom form control work with reactive Forms too (see your custom form control using reactive form)
<form [formGroup]="myForm">
<app-elements-input formControlName="name" ...>
</app-elements-input>
</form>
//and
myForm=new FormGroup(
{
name:new FormControl()
}
)
Well some times it's necesary know when the control is invalid, touched...
A easy way is add as provider NG_VALIDATORS
{provide: NG_VALIDATORS,
useExisting:forwardRef(() => InputComponent),
multi: true}
Add one variable, e.g.
control:any=null;
e implements Validator, that's add in the declaration and create a function validate where we give value to "control"
export class InputComponent implements ...,Validator {..}
public validate(c: FormControl) {
if (!this.control)
this.control=c;
return null;
// return (!this._value && !this.required)?{required:true}:null
}
So you can use in html some like
<span *ngIf="control?.invalid">*</span>
Don't forget indicate when the control is touched, in the example, we can use the event (blur) of the input
<input ... (blur)="onTouched()">
If you want make a component to control a formgroup it's only pass as `@Input()' the fromGroup or the formControl
<form [formGroup]="myForm">
<children [argformControl]="myForm.get('name')">
</children>
</form>
//and
@Input() argformControl:FormControl
or
<form [formGroup]="myForm">
<children [argFormGroup]="myForm">
</children>
</form>
//and
@Input() argFormGroup:FormGroup
Update this allow as, e.g. if we has an array of object like
data=[{name:'name',label:'Name'},{name:'surname',label:'Surname'}]
make some like
<!--I add a "clasic" *ngIf to avoid initialize problems
It can be placed in the form, or in children-->
<form *ngIf="myForm" [formGroup]="myForm">
<children [argFormGroup]="myForm" [data]="data">
</children>
</form>
And our children becomes
<div *ngFor="let item of data">
{{item.label}}<input [formControl]="argFormGroup.get(item.name)">
</div>
//and
@Input() argFormGroup:FormGroup
@Input() data:any[]
A custom formControl is a "black box". You send a value -a string, a object...- and you can modify this string or object. It's look like a "complex input" (a mat-date-picker, e.g. is a custom form control)
来源:https://stackoverflow.com/questions/56576068/how-to-implement-reactive-form-as-custom-component-using-ng-value-accessor