Reputation: 313
I keep getting an error "Cannot read property 'hasError' of undefined at CreateWorkOrderDialogComponent_Template (create-work-order-dialog.component.html:69)" when creating a validation on my nested formGroup. I have been trying to get the formcontrol with the below code but so far no success.
<mat-error *ngIf="form.get['client.name'].hasError('required')"
>Required
</mat-error>
My form with nested formGroups:
<div #container>
<form
[formGroup]="form"
(ngSubmit)="save()"
data-test="createFollowUpDialog"
autocomplete="off"
>
<h1 mat-dialog-title>Maak een nieuwe werkorder aan</h1>
<mat-dialog-content>
<div class="row mt-3">
<div class="col-md-12">
<h2>Werkorder informatie</h2>
<mat-form-field class="input">
<mat-label>Omschrijving van het probleem</mat-label>
<input
formControlName="leakageReason"
tabindex="1"
autocomplete="off"
matInput
placeholder="Omschrijving van probleem"
matTooltip="Omschrijving van het probleem"
/>
<mat-error
*ngIf="form.controls['leakageReason'].hasError('required')"
>Verplicht
</mat-error>
</mat-form-field>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="input">
<mat-label>Projectnummer</mat-label>
<input
formControlName="projectNumber"
tabindex="2"
autocomplete="off"
matInput
placeholder="Projectnummer"
/>
<mat-error
*ngIf="form.controls['projectNumber'].hasError('required')"
>Verplicht
</mat-error>
</mat-form-field>
</div>
</div>
<div formGroupName="client">
<h3>Gegevens van de opdrachtgever</h3>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="input">
<mat-label>Naam opdrachtgever</mat-label>
<input
formControlName="name"
tabindex="2"
autocomplete="off"
matInput
matTooltip="Naam van de opdrachtgever"
placeholder="Naam opdrachtgever"
/>
<mat-error *ngIf="form.get['client.name'].hasError('required')"
>Verplicht
</mat-error>
</mat-form-field>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="input">
<mat-label>Telnr. van opdrachtgever</mat-label>
<input
formControlName="phoneNumber"
tabindex="2"
autocomplete="off"
matInput
matTooltip="Telnr. van de opdrachtgever"
placeholder="Telnr. opdrachtgever"
/>
</mat-form-field>
</div>
</div>
</div>
<div formGroupName="customer">
<h3>Gegevens van de klant</h3>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="input">
<mat-label>Naam Klant</mat-label>
<input
formControlName="name"
tabindex="2"
autocomplete="off"
matInput
matTooltip="Naam van de klant"
placeholder="Naam klant"
/>
</mat-form-field>
</div>
</div>
<div class="row mt-3">
<div class="col-md-8">
<mat-form-field class="input">
<mat-label>Adres van klant</mat-label>
<input
formControlName="street"
tabindex="2"
autocomplete="off"
matInput
matTooltip="Straat van de klant"
placeholder="straat klant"
/>
</mat-form-field>
</div>
<div class="col-md-2">
<mat-form-field class="input addressWidth">
<mat-label>Huisnr.</mat-label>
<input
formControlName="houseNumber"
tabindex="2"
autocomplete="off"
matInput
matTooltip="Huisnummer"
placeholder="Huisnr."
/>
</mat-form-field>
</div>
<div class="col-md-2">
<mat-form-field class="input addressWidth">
<mat-label>toevoeging</mat-label>
<input
formControlName="houseNumberExt"
tabindex="2"
autocomplete="off"
matInput
matTooltip="Huisnummer toevoeging"
placeholder="toevoeging"
/>
</mat-form-field>
</div>
</div>
<div class="row mt-3">
<div class="col-md-4">
<mat-form-field class="input zipCodeWidth">
<mat-label>Postcode</mat-label>
<input
formControlName="zipCode"
tabindex="2"
autocomplete="off"
matInput
matTooltip="Postcode"
placeholder="Postcode"
/>
</mat-form-field>
</div>
<div class="col-md-4">
<mat-form-field class="input">
<mat-label>Plaats</mat-label>
<input
formControlName="city"
tabindex="2"
autocomplete="off"
matInput
matTooltip="Plaats"
placeholder="Plaats"
/>
</mat-form-field>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="datepicker">
<mat-label>Inspectiedatum </mat-label>
<input
matInput
formControlName="dateInspection"
tabindex="3"
[matDatepicker]="pickerIn"
/>
<mat-datepicker-toggle
tabindex="-1"
matSuffix
[for]="pickerIn"
></mat-datepicker-toggle>
<mat-datepicker #pickerIn></mat-datepicker>
</mat-form-field>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="input">
<mat-label>Status werkorder</mat-label>
<mat-select formControlName="status" name="status" tabindex="4">
<mat-option
*ngFor="let status of statusWerkOrder"
[value]="status"
>
{{ status }}
</mat-option>
</mat-select></mat-form-field
>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-slide-toggle
color="primary"
formControlName="followupInspection"
tabindex="5"
>Opvolgmelding?</mat-slide-toggle
>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-slide-toggle
color="primary"
formControlName="clientPresent"
tabindex="6"
>Is de klant aanwezig?</mat-slide-toggle
>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-slide-toggle
color="primary"
formControlName="visibleWaterDamage"
tabindex="7"
>Zichtbare waterschade?</mat-slide-toggle
>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="input">
<mat-label>Duur waterschade</mat-label>
<input
formControlName="visibleWaterDamagePeriod"
tabindex="8"
autocomplete="off"
matInput
matTooltip="Duur waterschade (dag, week, etc.)"
placeholder="Duur waterschade"
/>
</mat-form-field>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="input">
<mat-label>Soort gebouw</mat-label>
<mat-select
formControlName="buildingType"
name="buildingType"
tabindex="9"
>
<mat-option
*ngFor="let buildingType of buildingTypes"
[value]="buildingType"
>
{{ buildingType }}
</mat-option>
</mat-select></mat-form-field
>
</div>
</div>
<div class="row mt-3">
<div class="col-md-12">
<mat-form-field class="input">
<mat-label>Renovatie jaar</mat-label>
<input
formControlName="renovatedYear"
tabindex="10"
autocomplete="off"
matInput
placeholder="Renovatie jaar"
matTooltip="Renovatie jaar van het object"
/>
</mat-form-field>
</div>
</div>
<div class="divider"></div>
</mat-dialog-content>
<mat-dialog-actions class="d-flex">
<button
mat-raised-button
type="submit"
color="primary"
tabindex="11"
class="align-items-end"
matTooltip="Na opslaan worden de openstaande meldingen ververst zodat de melding direct ingepland kan worden"
>
Opslaan
</button>
<button
mat-raised-button
tabindex="12"
[mat-dialog-close]="true"
data-test="cancelCloseDialog"
class="align-items-end"
>
Annuleren
</button>
</mat-dialog-actions>
</form>
</div>
My typescript / component file where I create the form with formbuilder looks like this:
private buildForm() {
this.form = this.formBuilder.group({
projectNumber: new FormControl(this.data?.projectNumber, [
Validators.required,
]),
leakageReason: new FormControl(this.data?.leakageReason, [
Validators.required,
]),
dateInspection: new FormControl(this.data?.dateInspection, []),
followupInspection: new FormControl(this.data?.followupInspection, []),
clientPresent: new FormControl(this.data?.clientPresent, []),
visibleWaterDamage: new FormControl(this.data?.visibleWaterDamage, []),
visibleWaterDamagePeriod: new FormControl(
this.data?.visibleWaterDamagePeriod,
[]
),
buildingType: new FormControl(this.data?.buildingType, []),
renovatedYear: new FormControl(this.data?.renovatedYear, []),
status: new FormControl(this.data?.status, []),
client: this.formBuilder.group({
name: new FormControl(this.data?.client.name, [Validators.required]),
contactPerson: new FormControl(this.data?.client.contactPerson),
email: new FormControl(this.data?.client.email),
phoneNumber: new FormControl(this.data?.client.name),
street: new FormControl(this.data?.client.street),
houseNumber: new FormControl(this.data?.client.houseNumber),
houseNumberExt: new FormControl(this.data?.client.houseNumberExt),
zipCode: new FormControl(this.data?.client.zipCode),
city: new FormControl(this.data?.client.city),
attribute: new FormControl(this.data?.client.attribute),
}),
customer: this.formBuilder.group({
name: new FormControl(this.data?.customer.name, []),
contactPerson: new FormControl(this.data?.customer.contactPerson),
companyName: new FormControl(this.data?.customer.companyName),
street: new FormControl(this.data?.customer.street),
houseNumber: new FormControl(this.data?.customer.houseNumber),
houseNumberExt: new FormControl(this.data?.customer.houseNumberExt),
zipCode: new FormControl(this.data?.customer.zipCode),
city: new FormControl(this.data?.customer.city),
phoneNumber: new FormControl(this.data?.customer.phoneNumber, []),
}),
});
}
Can somebody please help me how to do this right? Many thanks, Pete
Upvotes: 0
Views: 1324
Reputation: 26730
As I've mentioned in my comment:
AbstractControl#get
(whichFormGroup
inherits from) is actually a function that returns the control you're trying to retrieve from the argument you've specified. What you're intending to use isFormGroup#controls
, which is a collection of controls declared as an object.
So you should change your code to either:
<mat-error *ngIf="form.get('client.name')?.hasError('required')">
Required
</mat-error>
Or:
<mat-error *ngIf="form.controls['client.name'].hasError('required')">
Required
</mat-error>
Upvotes: 1