I have a reactive form of which I am trying to get the value and assign it to a variable that is of a type defined in an interface. Although, this form is populated using the Google Places API (so all of the form controls are disabled and un-editable by the user, besides the first form control - that control being the field in which the user enters the initial address).
The reactive form is as follows:
ngOnInit() {
// Initialization of branch Address reactive form (Form 2 - Step 2)
this.addBranchAddressReactiveForm();
}
// Form Group 2 - Branch Address (Step 2)
addBranchAddressReactiveForm() {
this.addBranchAddressForm = this.fb.group({
// Branch Address Control
branchAddress: ['',
Validators.compose([Validators.required])
],
// Branch Street Name Control
branchStreetName: [{value: '', disabled: true},
Validators.compose([Validators.required])
],
// Branch Suburb Control
branchSuburb: [{value: '', disabled: true},
Validators.compose([Validators.required])
] ,
// Branch City Control
branchCity: [{value: '', disabled: true},
Validators.compose([Validators.required])
],
// Branch Province Control
branchProvince: [{value: '', disabled: true},
Validators.compose([Validators.required])
],
// Branch Country Control
branchCountry: [{value: '', disabled: true},
Validators.compose([Validators.required])
],
// Branch ZIP Control
branchZip: [{value: '', disabled: true},
Validators.compose([Validators.required])
]
});
}
As can be seen above, all controls but the first (branchAddress) are disabled - as these controls are populated upon address selection. When looking at the form itself in the component.html file, you can see that the "values" are dynamically assigned (as these values change depending on the address selected):
<form [formGroup]="addBranchAddressForm">
<ng-template matStepLabel>Enter New Branch Address</ng-template>
<div class="new-branch-form-container">
<!-- Main Branch Address Parameter (Input that generates the autocomplete dropdown list) -->
<mat-form-field>
<mat-label>Enter New Branch Address</mat-label>
<input matInput placeholder="Enter a location" formControlName="branchAddress" ngx-google-places-autocomplete #placesRef="ngx-places" [options]="addressOptions" (onAddressChange)="handleAddressChange($event)"/>
<mat-hint>Enter the address of the new branch and select the appropriate address item</mat-hint>
<mat-error>Please enter the new branch’s address</mat-error>
</mat-form-field>
<!-- Branch Street Name (Autofilled) -->
<mat-form-field>
<mat-label>Street Name</mat-label>
<input matInput formControlName="branchStreetName" readonly value={{streetName}}>
<mat-hint>The street name of the address selected</mat-hint>
<mat-error>Please enter the street name of the address specified</mat-error>
</mat-form-field>
<br>
<!-- Branch Suburb (Autofilled) -->
<mat-form-field>
<mat-label>Suburb</mat-label>
<input matInput formControlName="branchSuburb" readonly value={{suburb}}>
<mat-hint>The suburb of the address selected</mat-hint>
<mat-error>Please enter a valid suburb</mat-error>
</mat-form-field>
<br>
<!-- Branch City (Autofilled) -->
<mat-form-field>
<mat-label>City / Town</mat-label>
<input matInput formControlName="branchCity" readonly value={{city}}>
<mat-hint>The city of the address selected</mat-hint>
<mat-error>Please enter a valid city</mat-error>
</mat-form-field>
<!-- Branch Province (Autofilled) -->
<mat-form-field>
<mat-label>Province</mat-label>
<input matInput formControlName="branchProvince" readonly value="{{province}}">
<mat-hint>The province of the address selected</mat-hint>
<mat-error>Please enter the province of the address specified</mat-error>
</mat-form-field>
<br>
<!-- Branch Country (Autofilled) -->
<mat-form-field>
<mat-label>Country</mat-label>
<input matInput formControlName="branchCountry" readonly value={{country}}>
<mat-hint>The country of the address selected</mat-hint>
<mat-error>Please enter the country of the address specified</mat-error>
</mat-form-field>
<br>
<!-- Branch ZIP (Autofilled) -->
<mat-form-field>
<mat-label>ZIP</mat-label>
<input matInput formControlName="branchZip" readonly value={{zip}}>
<mat-hint>The ZIP / Postal code of the address selected</mat-hint>
<mat-error>Please enter the ZIP / Postal code of the address specified</mat-error>
</mat-form-field>
<br>
</div>
<!-- Button to navigate to previous step in stepper -->
<button mat-stroked-button matStepperPrevious color="primary">Back</button>
<!-- Button to navigate to next step in stepper (disabled until branch address form is valid) -->
<button mat-stroked-button matStepperNext color="primary" [disabled]="!addBranchAddressForm.valid">Next</button>
</form>
My issue is as follows. I want to be able to assign the values from this form to an object so that I can create a record in a database by linking up to a web API (not important) - although, when trying to assign the value of this form to the variable, the only "value" that is passed is that which is entered by the user him/herself. So for example, as can be seen below, the user types in "12" before selecting an address.

This "12" will be the only value captured by the code below (despite having the remaining controls populated after address selection):
const branch: Branch = this.addBranchDetailsForm.value;
So, when logging the above 'branch', the output is as follows, and not an object of all the values found within each separate form control:

I am populating the form control values as follows:
public handleAddressChange(address: any) {
// Full unformatted address (Not Displayed)
this.address = address.formatted_address;
console.log(this.address);
// Place id (Not Displayed)
this.placeId = address.place_id;
console.log(this.placeId);
// Latitude coordinate (Not Displayed)
this.latitude = address.geometry.location.lat();
console.log(this.latitude);
// Longitude coordinate (Not Displayed)
this.longitude = address.geometry.location.lng();
console.log(this.longitude);
// Reset street address on method refresh
this.streetName = "";
// Street number (Displayed i.t.o)
for (var i = 0; i < address.address_components.length; i++) {
for (var x = 0; x < address.address_components[i].types.length; x++) {
if (address.address_components[i].types[x] === "street_number") {
this.streetName = JSON.parse(JSON.stringify(address.address_components[i].long_name)) + " ";
}
}
}
// Street name (Displayed i.t.o)
for (var i = 0; i < address.address_components.length; i++) {
for (var x = 0; x < address.address_components[i].types.length; x++) {
if (address.address_components[i].types[x] === "route") {
this.streetName += JSON.parse(JSON.stringify(address.address_components[i].long_name));
}
}
}
// Reset suburb on method refresh
this.suburb = "";
// Suburb (Displayed)
for (var i = 0; i < address.address_components.length; i++) {
for (var x = 0; x < address.address_components[i].types.length; x++) {
if (address.address_components[i].types[x] === "sublocality") {
this.suburb = JSON.parse(JSON.stringify(address.address_components[i].long_name))
}
}
}
// Reset city on method refresh
this.city = "";
// City (Displayed)
for (var i = 0; i < address.address_components.length; i++) {
for (var x = 0; x < address.address_components[i].types.length; x++) {
if (address.address_components[i].types[x] === "locality") {
this.city = JSON.parse(JSON.stringify(address.address_components[i].long_name))
}
}
}
// Reset province on method refresh
this.province = "";
// Province (Displayed)
for (var i = 0; i < address.address_components.length; i++) {
for (var x = 0; x < address.address_components[i].types.length; x++) {
if (address.address_components[i].types[x] == "administrative_area_level_1") {
this.province = JSON.parse(JSON.stringify(address.address_components[i].long_name))
}
}
}
// Reset country on method refresh
this.country = "";
// Country (Displayed)
for (var i = 0; i < address.address_components.length; i++) {
for (var x = 0; x < address.address_components[i].types.length; x++) {
if (address.address_components[i].types[x] == "country") {
this.country = JSON.parse(JSON.stringify(address.address_components[i].long_name))
}
}
}
// Reset zip on method refresh
this.zip = "";
// ZIP (Displayed)
for (var i = 0; i < address.address_components.length; i++) {
for (var x = 0; x < address.address_components[i].types.length; x++) {
if (address.address_components[i].types[x] == "postal_code") {
this.zip = JSON.parse(JSON.stringify(address.address_components[i].long_name))
}
}
}
}
The handleAddressChange method accepts the address that is entered in the first control (field) of the form as seen below:
<!-- Main Branch Address Parameter (Input that generates the autocomplete dropdown list) -->
<mat-form-field>
<mat-label>Enter New Branch Address</mat-label>
<input matInput placeholder="Enter a location" formControlName="branchAddress" ngx-google-places-autocomplete #placesRef="ngx-places" [options]="addressOptions" (onAddressChange)="handleAddressChange($event)"/>
<mat-hint>Enter the address of the new branch and select the appropriate address item</mat-hint>
<mat-error>Please enter the new branch’s address</mat-error>
</mat-form-field>
When this method is activated, the variables as seen above (eg. this.suburb / this.city) are populated - and consequently these variables are displayed as part of the value attribute in the respective input field. For example:
<!-- Branch Suburb (Autofilled) -->
<mat-form-field>
<mat-label>Suburb</mat-label>
<input matInput formControlName="branchSuburb" readonly value={{suburb}}>
<mat-hint>The suburb of the address selected</mat-hint>
<mat-error>Please enter a valid suburb</mat-error>
</mat-form-field>
<br>
Above you can see that the variable (this.suburb) is set to the value attribute as {{suburb}}..
Any reason as to why this may be the case is appreciated. Thank you for your time.
Since there are disabled fields, formGroup.value doesn't return these value. You will need to call getRawValue() method of the formGroup to get field value irrespective of their enabled/disable state.
You need to do this:
const branch: Branch = this.addBranchDetailsForm.getRawValue();
From the Angular doc: https://angular.io/api/forms/FormGroup#getRawValue
getRawValue()- Retrieves all values regardless of disabled status. The value property is the best way to get the value of the group, because it excludes disabled controls in the FormGroup.
It is clear from your updated code that you are not setting the formGroup value and hence you are getting blank values despite using getRawValue() method. Here you are not updating the formControl.
this.streetName = JSON.parse(JSON.stringify(address.address_components[i].long_name)) + " ";
You need to change this to:
this. addBranchDetailsForm.get('branchStreetName').setValue(JSON.stringify(address.address_components[i].long_name)) + " ";
Same applies for all other fields.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With