Reputation: 11588
I would like to create a form and use a new, custom component for its controls. So I created a new component and included it into the parent form. But although the parent form has a formGroup, Angular complains that it does not.
The error:
Error: formControlName must be used with a parent formGroup directive. You'll want to add a formGroup directive and pass it an existing FormGroup instance (you can create one in your class).
The parent form has:
<form [formGroup]="learningObjectForm" (ngSubmit)="onSubmit()" novalidate>
<div>
<button type="submit"
[disabled]="learningObjectForm.pristine">Save</button>
</div>
<ava-form-control [label]="'Resource'"></ava-form-control>
</form>
And in the .ts:
constructor(private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.learningObjectForm = this.fb.group({
text: '',
});
}
In the custom component I have
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'ava-form-control',
template: ` <div>
<label>{{label}} :</label>
<input formControlName="{{name}}">
</div>
`
})
export class FormControlComponent implements OnInit {
@Input() label: string;
@Input() name: string;
constructor() {}
ngOnInit() {
if (this.name === undefined) {
// turns 'The Label' into 'theLabel'
this.name = this.label[0].toLowerCase().concat(this.label.slice(1));
this.name = this.name.split(' ').join('');
console.log(this.label, this.name);
}
}
}
Upvotes: 1
Views: 2003
Reputation: 3149
I played around with the accepted answer for a long time, and never had any luck.
I had much better results implementing the ControlValueAccessor interface as shown here: https://alligator.io/angular/custom-form-control/
It's actually pretty simple, I also rigged up an Example StackBlitz
Upvotes: 1
Reputation: 29715
You should also be passing the formGroup
instance along with control name
to your custom component
. And then create a form control
under that formGroup
in custom component. Your custom component will create the control virtually under the same formGroup that you have provided.
<form [formGroup]="learningObjectForm" (ngSubmit)="onSubmit()" novalidate>
<div>
<button type="submit"
[disabled]="learningObjectForm.pristine">Save</button>
</div>
<ava-form-control [label]="'Resource'" [formGroup]="learningObjectForm" [controlName]="'mycontrol'"></ava-form-control>
</form>
custom.component.ts
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'ava-form-control',
template: ` <div>
<label>{{label}} :</label>
<input [formControl]="formGroup.controls[controlName]>
</div>
`
})
export class FormControlComponent implements OnInit {
@Input() label: string;
@Input() formGroup: FormGroup;
@Input() controlName: string;
constructor() {}
ngOnInit() {
let control: FormControl = new FormControl('', Validators.required);
this.formGroup.addControl(this.controlName, control);
}
}
With this your parent component can access all the form controls defined within their respective custom components.
Upvotes: 3