I am building a simple Google Places Autocomplete Angular2 directive but the problem is that cannot get any prediction (the response is always empty?!)...
As a proof of concept I created the simplest possible code snippet as a reference:
<!DOCTYPE html>
<html>
<head>
<script src="https://maps.googleapis.com/maps/api/js?key=[MY_API_KEY]&libraries=places" async defer></script>
</head>
<body>
<button type="button" onclick="go()">go</button>
<input id="autocomplete" type="text"></input>
<script>
var autocomplete = null;
function go() {
autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocomplete')), {
types: ['geocode']
});
}
</script>
</body>
</html>
The above code works - I can get predictions after clicking Go button.
Now, Angular2 scenario:
My _Layout.cshtml file has the following tag in head section:
<script src="https://maps.googleapis.com/maps/api/js?key=[MY_API_KEY]&libraries=places" async defer></script>
My directive:
import { Directive, ElementRef, Input } from '@angular/core'; declare var google: any; @Directive({ selector: '[googleplaces]' }) export class GooglePlacesDirective { autocomplete: any; constructor(private el: ElementRef) { } ngAfterContentInit() { this.autocomplete = new google.maps.places.Autocomplete( (this.el.nativeElement), { types: ['geocode', 'cities'] }); } }
And simple Angular component:
<form [formGroup]="companyForm">
.
.
.
<div class="form-group">
<label for="Location">Location</label>
<input type="text"
class="form-control"
id="Location"
fromControlName="Location"
googleplaces>
</div>
</form>
The Scenario 2 (angular) doesn't work. The facts:
Also, Google API Console says everything is as it should be?! Here is the screenshot:
What can be in question here? Thanks...
import {Directive, ElementRef, EventEmitter, Output} from '@angular/core';
import {NgModel} from '@angular/forms';
declare var google:any;
@Directive({
selector: '[Googleplace]',
providers: [NgModel],
host: {
'(input)' : 'onInputChange()'
}
})
export class GoogleplaceDirective {
@Output() setAddress: EventEmitter<any> = new EventEmitter();
modelValue:any;
autocomplete:any;
private _el:HTMLElement;
constructor(el: ElementRef,private model:NgModel) {
this._el = el.nativeElement;
this.modelValue = this.model;
var input = this._el;
this.autocomplete = new google.maps.places.Autocomplete(input, {});
google.maps.event.addListener(this.autocomplete, 'place_changed', ()=> {
var place = this.autocomplete.getPlace();
this.invokeEvent(place);
});
}
invokeEvent(place:Object) {
this.setAddress.emit(place);
}
onInputChange() {
console.log(this.model);
}
}
To use
<input type="text" class="form-control" placeholder="Location" name="Location" [(ngModel)]="address" #LocationCtrl="ngModel"
Googleplace (setAddress)="getAddressOnChange($event,LocationCtrl)">
@Habeeb's answer is a great start, but this is a cleaner implementation. First install the googlemaps typings npm install --save-dev @types/googlemaps
and import them somewhere in your app import {} from '@types/googlemaps'
.
import { Directive, ElementRef, EventEmitter, OnInit, Output } from '@angular/core';
@Directive({
// xx is your app's prefix
selector: '[xxPlaceLookup]'
})
export class PlaceLookupDirective implements OnInit {
@Output() onSelect: EventEmitter<any> = new EventEmitter();
private element: HTMLInputElement;
constructor(el: ElementRef) {
this.element = el.nativeElement;
}
ngOnInit() {
const autocomplete = new google.maps.places.Autocomplete(this.element, {
types: ['establishment'],
componentRestrictions: {country: 'us'}
});
google.maps.event.addListener(autocomplete, 'place_changed', () => {
const place = autocomplete.getPlace();
this.onSelect.emit(place);
});
}
}
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