Skip to content

Commit 5584cae

Browse files
committed
feat(package): added MatGoogleMapsAutocompleteComponent | mat-google-maps-autocomplete
1 parent 60e44cd commit 5584cae

4 files changed

+169
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<mat-form-field class="full-width" appearance="outline">
2+
<mat-label>Address</mat-label>
3+
<input matInput
4+
[(ngModel)]="address"
5+
(change)="onQuery($event)"
6+
placeholder="Please enter the address"
7+
class="form-control"
8+
#search
9+
MatValidateAddress
10+
required>
11+
<mat-error *ngIf="addressSearchControl.hasError('required')">
12+
The address is <strong>required</strong>
13+
</mat-error>
14+
<mat-error *ngIf="addressSearchControl.hasError('validateAddress')">
15+
The address is <strong>not valid</strong>
16+
</mat-error>
17+
</mat-form-field>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.full-width {
2+
width: 100%;
3+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { By } from '@angular/platform-browser';
3+
import { DebugElement } from '@angular/core';
4+
5+
import { MatGoogleMapsAutocompleteComponent } from './mat-google-maps-autocomplete.component';
6+
7+
describe('LibComponent', function () {
8+
let de: DebugElement;
9+
let comp: MatGoogleMapsAutocompleteComponent;
10+
let fixture: ComponentFixture<MatGoogleMapsAutocompleteComponent>;
11+
12+
beforeEach(async(() => {
13+
TestBed.configureTestingModule({
14+
declarations: [MatGoogleMapsAutocompleteComponent]
15+
})
16+
.compileComponents();
17+
}));
18+
19+
beforeEach(() => {
20+
fixture = TestBed.createComponent(MatGoogleMapsAutocompleteComponent);
21+
comp = fixture.componentInstance;
22+
de = fixture.debugElement.query(By.css('p.description'));
23+
});
24+
25+
it('should create component', () => expect(comp).toBeDefined());
26+
27+
it('should have expected <p> text', () => {
28+
fixture.detectChanges();
29+
const p = de.nativeElement;
30+
const description = 'Autocomplete input component for google-maps built with angular material design';
31+
expect(p.textContent).toEqual(description);
32+
});
33+
});
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import {Component, ElementRef, EventEmitter, Input, NgZone, OnInit, Output, ViewChild} from '@angular/core';
2+
import {FormControl, Validators} from '@angular/forms';
3+
import {MatValidateAddressDirective} from '../directives/address-validator/mat-address-validator.directive';
4+
import {MapsAPILoader} from '@agm/core';
5+
import PlaceResult = google.maps.places.PlaceResult;
6+
7+
export interface Location {
8+
latitude: number,
9+
longitude: number;
10+
}
11+
12+
@Component({
13+
selector: 'mat-google-maps-autocomplete',
14+
templateUrl: './mat-google-maps-autocomplete.component.html',
15+
styleUrls: ['./mat-google-maps-autocomplete.component.scss']
16+
})
17+
export class MatGoogleMapsAutocompleteComponent implements OnInit {
18+
19+
@ViewChild('search')
20+
public searchElementRef: ElementRef;
21+
22+
@Input()
23+
address: PlaceResult | string;
24+
25+
@Input()
26+
country = 'de';
27+
28+
@Input()
29+
types: string[] = ['address'];
30+
31+
@Output()
32+
onChange: EventEmitter<PlaceResult | string | null> = new EventEmitter<PlaceResult | string | null>();
33+
34+
@Output()
35+
onAddressSelected: EventEmitter<PlaceResult> = new EventEmitter<PlaceResult>();
36+
37+
@Output()
38+
onLocationSelected: EventEmitter<Location> = new EventEmitter<Location>();
39+
40+
private onNewPlaceResult: EventEmitter<any> = new EventEmitter();
41+
private addressValidator: MatValidateAddressDirective = new MatValidateAddressDirective();
42+
43+
public addressSearchControl: FormControl = new FormControl({value: null}, Validators.compose([
44+
Validators.required,
45+
this.addressValidator.validate()])
46+
);
47+
48+
constructor(private _mapsAPILoader: MapsAPILoader,
49+
private _ngZone: NgZone) {
50+
}
51+
52+
ngOnInit(): void {
53+
this.addressValidator.subscribe(this.onNewPlaceResult);
54+
55+
const options = {
56+
types: ['address'],
57+
componentRestrictions: {country: 'de'}
58+
};
59+
60+
this._mapsAPILoader
61+
.load()
62+
.then(() => {
63+
/* Instantiate a placesService */
64+
// if (this.immoAd.address.place_id) {
65+
// const placesService = new google.maps.places.PlacesService(this.searchElementRef.nativeElement);
66+
// placesService.getDetails({
67+
// placeId: this.immoAd.address.place_id
68+
// }, (placeResult: PlaceResult, status) => {
69+
// console.log('status: ', status);
70+
// if (status === google.maps.places.PlacesServiceStatus.OK) {
71+
// console.log('place result: ', placeResult);
72+
// this.address = placeResult;
73+
//
74+
// if (placeResult.place_id) {
75+
// this.updateAddress(placeResult)
76+
// }
77+
// }
78+
// });
79+
// }
80+
const autocomplete = new google.maps.places.Autocomplete(this.searchElementRef.nativeElement, options);
81+
autocomplete.addListener('place_changed', () => {
82+
this._ngZone.run(() => {
83+
// get the place result
84+
const place: PlaceResult = autocomplete.getPlace();
85+
86+
if (!place.place_id || place.geometry === undefined || place.geometry === null) {
87+
// place result is not valid
88+
return;
89+
} else {
90+
// show dialog to select a address from the input
91+
// emit failed event
92+
}
93+
this.address = place.formatted_address;
94+
this.onAddressSelected.emit(place);
95+
this.onLocationSelected.emit(
96+
{
97+
latitude: place.geometry.location.lat(),
98+
longitude: place.geometry.location.lng()
99+
})
100+
});
101+
});
102+
})
103+
.catch((err) => console.log(err));
104+
}
105+
106+
public onQuery(event: any) {
107+
console.log('onChange()', event);
108+
this.onChange.emit(this.address);
109+
}
110+
111+
private resetAddress() {
112+
this.address = null;
113+
this.addressSearchControl.updateValueAndValidity();
114+
}
115+
116+
}

0 commit comments

Comments
 (0)