I have an angular reactive form that I want to add a form group from a the different file. I can't get it to work. I have a function that return an untyped form group:
public getEmptyTemplateForm(): FormGroup {
const template = new FormGroup({
'id': this.formBuilder.nonNullable.control<number>(0),
'name': this.formBuilder.nonNullable.control<string>(''),
'expirationType': this.formBuilder.nonNullable.control<number | string> (
'', [Validators.required, Validators.pattern('^[0-9]*$')],
),
'expirationDate': this.formBuilder.nonNullable.control(
this.moment(new Date()), []
),
'expirationDays': this.formBuilder.nonNullable.control<number | string> (
'', [Validators.pattern('^[0-9]*$')],
),
'serverCount': this.formBuilder.nonNullable.control<number | string> (
'', [Validators.required, Validators.pattern('^[0-9]*$')]
),
'appCount': this.formBuilder.nonNullable.control<number | string> (
'', [Validators.required, Validators.pattern('^[0-9]*$')]
),
'featuresList': this.formBuilder.array<number>([]),
});
return template;
}
And the main form:
licenseForm = this.fb.group({
id: this.fb.nonNullable.control<number | undefined>(undefined),
activationKey: ['', [Validators.required]],
enabled: [true],
customerId: this.fb.nonNullable.control<number | undefined>(undefined),
customerName: ['', [Validators.required]],
// template: this.fb.nonNullable.group<Partial<Template>>({}),
hostId: [''],
licenseText: [''],
});
And than tried to put the following code in either the constructor or ngOnInit:
const emptyTemplateForm = this.emptyTemplateFormService.getEmptyTemplateForm();
this.licenseForm.addControl("template", emptyTemplateForm)
Using setControl give the this error:
Error: Cannot find control with path: 'template -> id' (etc.)
and addControl gives the following error:
No overload matches this call. Overload 1 of 2, '(this: FormGroup<{ [key: string]: AbstractControl<any, any>; }>, name: string, control: AbstractControl<any, any>, options?: { emitEvent?: boolean | undefined; } | undefined): void', gave the following error. The 'this' context of type 'FormGroup<{ id: FormControl<number | undefined>; activationKey: FormControl<string | null>; enabled: FormControl<boolean | null>; customerId: FormControl<...>; customerName: FormControl<...>; hostId: FormControl<...>; licenseText: FormControl<...>; }>' is not assignable to method's 'this' of type 'FormGroup<{ [key: string]: AbstractControl<any, any>; }>'. Type '{ [key: string]: AbstractControl<any, any>; }' is missing the following properties from type '{ id: FormControl<number | undefined>; activationKey: FormControl<string | null>; enabled: FormControl<boolean | null>; customerId: FormControl<...>; customerName: FormControl<...>; hostId: FormControl<...>; licenseText: FormControl<...>; }': id, activationKey, enabled, customerId, and 3 more. Overload 2 of 2, '(name: "id" | "activationKey" | "enabled" | "customerId" | "customerName" | "hostId" | "licenseText", control: FormControl<number | undefined> | FormControl<string | null> | FormControl<...>, options?: { ...; } | undefined): void', gave the following error. Argument of type '"template"' is not assignable to parameter of type '"id" | "activationKey" | "enabled" | "customerId" | "customerName" | "hostId" | "licenseText"'.
The HTML:
//Main component
<div formGroupName="template" >
<div >
<label for="templateId">Template:</label>
<select
formControlName="id"
(change)="changeTemplate()"
>
<option
*ngFor="let template of templates"
[ngValue]="template.id"
>
{{ template.name }}
</option>
</select>
</div>
<app-license-restrictions-fields groupName="template"></app-license-restrictions-fields>
</div>
// Template component
<form autocomplete="off" [formGroup]="template">
<div>
<label for="serverCount">Max. Servers:</label>
<input
type="number"
formControlName="serverCount"
id="serverCount"
>
</div>
<div>
<label for="appCount">Max. Applications:</label>
<input
type="number"
formControlName="appCount"
id="appCount"
>
</div>
<div >
<label for="expirationType">Expiration Type:</label>
<mat-button-toggle-group
formControlName="expirationType"
id="expirationType"
>
<mat-button-toggle [value]="0" >Date</mat-button-toggle>
<mat-button-toggle [value]="1" >Days</mat-button-toggle>
</mat-button-toggle-group>
</div>
<section *ngIf="template.get('expirationType')?.value === 0">
<label for="expirationDate" >Expiration Date:</label>
<mat-form-field >
<input
matInput
[matDatepicker]="picker"
formControlName="expirationDate"
id="expirationDate"
name="expirationDate"
(dateChange)="updateExpirationDays()"
>
<mat-hint>MM/DD/YYYY</mat-hint>
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
</section>
<div *ngIf="template.get('expirationType')?.value === 1" >
<label for="expirationDays">Days To Expiration:</label>
<input
type="number"
formControlName="expirationDays"
id="expirationDays"
(change)="updateExpirationDate()"
>
</div>
<app-feature-list [features]="features" (selectFeature)="onSelectFeature($event)"></app-feature-list>
</form>
Please, How can I make it to work?
CodePudding user response:
Try this
licenseForm!: FormGroup;
constructor(
private fb: FormBuilder,
private formTemplateService: FormTemplateService
) {}
ngOnInit(): void {
this.createLicenseForm();
}
createLicenseForm = () => {
this.licenseForm = this.fb.group({
// ...
template: this.formTemplateService.getTemplateFormGroup(),
// ...
});
}
Stackblitz Link: https://stackblitz.com/edit/codeandcloud-so-74178980