Skip to content

Commit a576759

Browse files
authored
refactor: update location component to inherit Field Base class (#397)
1 parent 72926b7 commit a576759

File tree

2 files changed

+22
-127
lines changed

2 files changed

+22
-127
lines changed

packages/angular-sdk-components/src/lib/_components/field/location/location.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
matInput
77
type="text"
88
[placeholder]="placeholder"
9-
[formControl]="searchControl"
9+
[formControl]="fieldControl"
1010
[required]="bRequired$"
1111
[matAutocomplete]="auto"
1212
[attr.data-test-id]="testId"
1313
(blur)="fieldOnBlur()"
1414
/>
15-
<mat-error *ngIf="searchControl.invalid">{{ getErrorMessage() }}</mat-error>
15+
<mat-error *ngIf="fieldControl.invalid">{{ getErrorMessage() }}</mat-error>
1616
<button
1717
mat-icon-button
1818
matSuffix

packages/angular-sdk-components/src/lib/_components/field/location/location.component.ts

Lines changed: 20 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
1-
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
1+
import { Component, inject } from '@angular/core';
22
import { CommonModule } from '@angular/common';
3-
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
3+
import { ReactiveFormsModule } from '@angular/forms';
44
import { MatFormFieldModule } from '@angular/material/form-field';
55
import { MatInputModule } from '@angular/material/input';
66
import { MatAutocompleteModule } from '@angular/material/autocomplete';
77
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
88
import { MatIconModule } from '@angular/material/icon';
99
import { MatButtonModule } from '@angular/material/button';
1010
import { GoogleMapsModule } from '@angular/google-maps';
11+
import { debounceTime, from, of, switchMap } from 'rxjs';
1112

12-
import { debounceTime, from, interval, of, switchMap } from 'rxjs';
13-
14-
import { AngularPConnectData, AngularPConnectService } from '../../../_bridge/angular-pconnect';
13+
import { FieldBase } from '../field.base';
1514
import { GoogleMapsLoaderService } from '../../../_services/google-maps-loader.service';
16-
import { Utils } from '../../../_helpers/utils';
1715
import { handleEvent } from '../../../_helpers/event-util';
1816

1917
import { PConnFieldProps } from '../../../_types/PConnProps.interface';
@@ -41,147 +39,61 @@ interface LocationProps extends PConnFieldProps {
4139
templateUrl: './location.component.html',
4240
styleUrl: './location.component.scss'
4341
})
44-
export class LocationComponent implements OnInit, OnDestroy {
45-
@Input() pConn$: typeof PConnect;
46-
@Input() formGroup$: FormGroup;
42+
export class LocationComponent extends FieldBase {
43+
private loader = inject(GoogleMapsLoaderService);
4744

4845
private autocompleteService!: google.maps.places.AutocompleteService;
4946
private geocoder!: google.maps.Geocoder;
5047

5148
// Dom variables
5249
mapReady = false;
5350
isLocating = false;
54-
searchControl = new FormControl('');
5551
showMap = true;
5652
filteredOptions: string[] = [];
5753
center: google.maps.LatLngLiteral;
5854
markerPosition: google.maps.LatLngLiteral | null = null;
5955

60-
// Used with AngularPConnect
61-
angularPConnectData: AngularPConnectData = {};
6256
configProps$: LocationProps;
63-
label$ = '';
6457
onlyCoordinates: boolean;
6558
coordinates: string;
66-
bRequired$ = false;
67-
bReadonly$ = false;
6859
showMapReadOnly$: boolean;
69-
bDisabled$ = false;
70-
bVisible$ = true;
71-
controlName$: string;
72-
bHasForm$ = true;
73-
testId = '';
74-
helperText: string;
75-
placeholder: string;
76-
actionsApi: object;
7760
valueProp: string;
7861
coordinatesProp: string;
7962

80-
constructor(
81-
private loader: GoogleMapsLoaderService,
82-
private angularPConnect: AngularPConnectService,
83-
private utils: Utils,
84-
private cdRef: ChangeDetectorRef
85-
) {}
63+
override async ngOnInit() {
64+
super.ngOnInit();
8665

87-
async ngOnInit() {
8866
// Loading map
8967
const apiKey = this.pConn$.getGoogleMapsAPIKey();
9068
await this.loader.load(apiKey);
9169
this.mapReady = true;
9270
this.initializeGoogleServices();
9371
this.getPlacePredictions();
94-
95-
this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
96-
this.controlName$ = this.angularPConnect.getComponentID(this);
97-
this.checkAndUpdate();
98-
99-
if (this.formGroup$) {
100-
// add control to formGroup
101-
this.formGroup$.addControl(this.controlName$, this.searchControl);
102-
this.bHasForm$ = true;
103-
} else {
104-
this.bReadonly$ = true;
105-
this.bHasForm$ = false;
106-
}
10772
}
10873

109-
ngOnDestroy(): void {
110-
if (this.formGroup$) {
111-
this.formGroup$.removeControl(this.controlName$);
112-
}
113-
114-
if (this.angularPConnectData.unsubscribeFn) {
115-
this.angularPConnectData.unsubscribeFn();
116-
}
117-
}
118-
119-
checkAndUpdate() {
120-
const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this);
121-
if (bUpdateSelf) {
122-
this.updateSelf();
123-
}
124-
}
74+
/**
75+
* Updates the component when there are changes in the state.
76+
*/
77+
override updateSelf(): void {
78+
// Resolve configuration properties
79+
this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as LocationProps;
12580

126-
onStateChange() {
127-
setTimeout(() => {
128-
this.checkAndUpdate();
129-
}, 0);
130-
}
81+
// Update component common properties
82+
this.updateComponentCommonProperties(this.configProps$);
13183

132-
updateSelf(): void {
133-
this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as LocationProps;
134-
if (this.configProps$.visibility != null) {
135-
this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
136-
}
13784
this.onlyCoordinates = !!this.configProps$.onlyCoordinates;
138-
this.label$ = this.configProps$.label;
139-
this.testId = this.configProps$.testId;
140-
141-
this.helperText = this.configProps$.helperText || '';
142-
this.placeholder = this.configProps$.placeholder || '';
14385
this.showMapReadOnly$ = !!this.configProps$.showMapReadOnly;
144-
if (this.configProps$.readOnly != null) {
145-
this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
146-
}
14786
this.showMap = this.bReadonly$ ? this.showMapReadOnly$ : !!this.configProps$.showMap;
87+
14888
if (this.configProps$.coordinates) {
14989
const latAndLong: number[] = this.configProps$.coordinates.split(',').map(Number);
15090
const latitude = Number(latAndLong[0]);
15191
const longitude = Number(latAndLong[1]);
15292
this.updateMap(latitude, longitude, this.configProps$.value);
15393
}
154-
// // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
155-
setTimeout(() => {
156-
if (this.configProps$.required != null) {
157-
this.bRequired$ = this.utils.getBooleanValue(this.configProps$.required);
158-
}
159-
this.cdRef.detectChanges();
160-
});
161-
// // disabled
162-
if (this.configProps$.disabled != undefined) {
163-
this.bDisabled$ = this.utils.getBooleanValue(this.configProps$.disabled);
164-
}
16594

166-
if (this.bDisabled$ || this.bReadonly$) {
167-
this.searchControl.disable();
168-
} else {
169-
this.searchControl.enable();
170-
}
171-
172-
this.actionsApi = this.pConn$.getActionsApi();
17395
this.valueProp = this.pConn$.getStateProps().value;
17496
this.coordinatesProp = this.pConn$.getStateProps().coordinates;
175-
176-
// // trigger display of error message with field control
177-
if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
178-
const timer = interval(100).subscribe(() => {
179-
this.searchControl.setErrors({ message: true });
180-
this.searchControl.markAsTouched();
181-
182-
timer.unsubscribe();
183-
});
184-
}
18597
}
18698

18799
onOptionSelected(event: any) {
@@ -236,23 +148,6 @@ export class LocationComponent implements OnInit, OnDestroy {
236148
}
237149
}
238150

239-
getErrorMessage() {
240-
let errMessage = '';
241-
242-
// look for validation messages for json, pre-defined or just an error pushed from workitem (400)
243-
if (this.searchControl.hasError('message')) {
244-
errMessage = this.angularPConnectData.validateMessage ?? '';
245-
return errMessage;
246-
}
247-
if (this.searchControl.hasError('required')) {
248-
errMessage = 'You must enter a value';
249-
} else if (this.searchControl.errors) {
250-
errMessage = this.searchControl.errors.toString();
251-
}
252-
253-
return errMessage;
254-
}
255-
256151
private tryGetLocation(retryCount: number) {
257152
navigator.geolocation.getCurrentPosition(
258153
position => {
@@ -312,7 +207,7 @@ export class LocationComponent implements OnInit, OnDestroy {
312207
}
313208

314209
private getPlacePredictions() {
315-
this.searchControl.valueChanges
210+
this.fieldControl.valueChanges
316211
.pipe(
317212
debounceTime(300),
318213
switchMap(value => this.getSuggestions(value || ''))
@@ -371,7 +266,7 @@ export class LocationComponent implements OnInit, OnDestroy {
371266
}
372267

373268
private updateProps() {
374-
handleEvent(this.actionsApi, 'change', this.valueProp, this.searchControl.value);
269+
handleEvent(this.actionsApi, 'change', this.valueProp, this.fieldControl.value);
375270
handleEvent(this.actionsApi, 'change', this.coordinatesProp, this.coordinates);
376271
}
377272

@@ -380,6 +275,6 @@ export class LocationComponent implements OnInit, OnDestroy {
380275
}
381276

382277
private setLocationValue(value: string) {
383-
this.searchControl.setValue(value, { emitEvent: false });
278+
this.fieldControl.setValue(value, { emitEvent: false });
384279
}
385280
}

0 commit comments

Comments
 (0)