How can i get address components using Google's AutocompleteService via JavaScript? - javascript

Google offers different ways to use the Place Autocomplete API. Two of these being the Autocomplete and AutocompleteService classes. Whenever I use the Autocomplete class I get the address components without a problem. However, whenever I use the AutocompleteService the address components are missing. I do get an address but not in the same way I do with Autocomplete (I can parse into city, street, state, etc.).
Is there a way I can get the address components field using AutocompleteService WITHOUT making an additional call with the place ID ?
Autocomplete example
function initAutocomplete() {
autocomplete = new google.maps.places.Autocomplete(document.getElementById('search'), {
componentRestrictions: { country: ["us", "ca"] },
fields: ["address_components", "geometry"],
types: ["address"],
});
autocomplete.addListener("place_changed", () => {
const place = autocomplete.getPlace(); // Includes Address Components and Geometry (Lat and Lng)
});
}
AutocompleteService example
function initAutocompleteService() {
const service = new google.maps.places.AutocompleteService();
service.getPlacePredictions({
input: "1600 Amphitheatre",
componentRestrictions: {
country: 'us'
},
types: ['address']
}, (predictions, status) => {
console.log(predictions); // It shows the address a single string but missing address components
});
}

Is there a way I can get the address components field using AutocompleteService WITHOUT making an additional call with the place ID ?
Short answer: No, you can't.
If you are worried about billing, you should use Session tokens.
As per the documentation:
AutocompleteService.getPlacePredictions() uses session tokens to group together autocomplete requests for billing purposes.
The interesting part:
You can use the same session token to make a single Place Details request on the place that results from a call to AutocompleteService.getPlacePredictions(). In this case, the autocomplete request is combined with the Place Details request, and the call is charged as a regular Place Details request. There is no charge for the autocomplete request.
Google provides an example on how to create the Session token:
// Create a new session token.
var sessionToken = new google.maps.places.AutocompleteSessionToken();
// Pass the token to the autocomplete service.
var autocompleteService = new google.maps.places.AutocompleteService();
autocompleteService.getPlacePredictions({
input: 'pizza near Syd',
sessionToken: sessionToken
},
displaySuggestions);
When user selects a place, you can reuse that same session token to retrieve the place details with the fields you are interested in, in order to get billed only for the place details request (as stated above).
You might also want to read Cost optimization best practices.
Programmatic implementation
Use a session token with your Place Autocomplete requests. When requesting Place Details about the selected prediction, include the following parameters:
The place ID from the Place Autocomplete response
The session token used in the Place Autocomplete request
The fields parameter specifying the place data fields you need
As you can see, the PlaceDetailsRequest interface takes an optional sessionToken parameter.

Related

How to Integrate Google autocomplete search box EFFICIENTLY with my Angular?

I have created an Angular 8 project and I used a wrapper for Google Places Autocomplete js library called ngx-google-places-autocomplete
The instructions are pretty straight forward and here is what I have so far in my project:
index.html
<script src="https://maps.googleapis.com/maps/api/js?key=<API_KEY>&libraries=places&language=en"></script>
app.module.ts
I have imported the library GooglePlaceModule as the following:
import { GooglePlaceModule } from "ngx-google-places-autocomplete";
#NgModule({
imports: [GooglePlaceModule, BrowserModule, FormsModule, ...],
....
})
app.component.html
<input
ngx-google-places-autocomplete
[options]='options'
placeholder="Enter a location"
autocomplete="off"
(onAddressChange)="handleAddressChange($event)"/>
app.component.ts
I have defined my options and the handleAddressChange() like the following
options: Options = {
bounds: undefined,
fields: ['address_component'],
strictBounds: false,
types: ['address'],
origin: undefined,
componentRestrictions: undefined
};
handleAddressChange(address: Address) {
console.log(address);
}
Yes, the autocomplete is working fine after I made sure I enabled Map Javascript API and Places API
However, the billing documentation wasn't clear where every key stroke was a an API request and that there is a way to get charged properly per user session (session token) so anything you do within your session does not count as an API request until handleAddressChange(address: Address) gets exectued.
My understanding, the documentation says that I need to inject a UUID (V4 recommended) into my script tag in my index.html like the following
<script src="https://maps.googleapis.com/maps/api/js?key=<API_KEY>&libraries=places&language=en&sessiontoken=<UUID>"></script>
I know I can use Google namespace to generate those UUIDs or sessionToken like the following:
var sessionToken = new google.maps.places.AutocompleteSessionToken();
However, I am not sure if there a proper way to inject the sessionToken into my <script> tag without violating XSS and I am not sure if this is the right way to implement a session tokens? I want to give the user one session token when the page loads so they can type/play with my search box they wanted with only one API request. I want to be in control of when the session token gets generated, injected, then destroyed in my app.
Those session tokens is used to REDUCE the amount of API requests so I don't get charged extra on my billing account.

Google Maps API to get location address as well as domain information

I am working with Google Maps Javascript API & using places library. Although I am able to get the location address but I also need to get the location domain information like suppose if the location is a business & also has a website URL linked to that location. Can someone guide me to the right API or library that also provides the Domain information of a location ? So far I have not come across any.
Use places library to get other information as well
//make a request variable attaching the data you require , make sure to use only those which you require as detail request are billed separately
var request = {
query: 'yourquery',
fields: ['address_component', 'website']
};
service = new google.maps.places.PlacesService(map);
service.getDetails(request, callback);
//Here you get the result
function callback(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var website = place.website; // get the website, may be empty
var type = place.address_component.types[0]; //this is an array and can be empty
}
}

Prevent google geocoder API from returning status 'OK' when only single, double or rand chars are used

If I pass in just a 'S' to the geocode api I get a result back with status of "OK". Is there any way to just get a status back of 'OK' when a City or Town is entered? So that I don't get false results when a user enters in stuff like
ex. 'S' or 'SA' or 'TTT'
this.geocoder = new google.maps.Geocoder();
this.geocoder.geocode({
address: this.registerForm.get('city').value,
componentRestrictions: {
country: 'US'
}
},
(results, status) => {
// do stuff here.
});
Geocoding API is not an address validation service. It was never designed for this purpose. The main idea of Geocoding API is providing best match for your input text according to certain criteria. So, it will always try return a result even if input text doesn't have much sense. Unfortunately, there is no way to change this behavior of service.
If you would like your users to send only valid addresses, have a look at autocomplete service (type-ahead-search behavior). This way users will select one of suggested addresses and you can get detailed information for selected place ID (which exists in Google database).
For further details look at the autocomplete documentation:
https://developers.google.com/maps/documentation/javascript/places-autocomplete
I hope this helps!

Get ZIP codes of particular country using google map

I am using maps.googleapis.com/maps/api in codeigniter to display auto complete location when user types zip address. I have two input field from first user will select country and in second filed he will type his zip code and from google autocomplete he will select his address.
var directionsService = new google.maps.DirectionsService();
google.maps.event.addDomListener(window, 'load', function () {
new google.maps.places.SearchBox(document.getElementById('zip'));
directionsDisplay = new google.maps.DirectionsRenderer({ 'draggable': true });
});
It is working fine but now I want to show zip codes only from selected country. Means if user select Australia as country and type zip like 2127 then google api should show addresses in Australia having 2127 in address
Google maps JS api provides two kinds of widgets for autocomplete. One is google.maps.places.SearchBox you are using, which only offers restriction by Latitude and Longitude bounds and then there is google.maps.places.Autocomplete which provides country restriction (and much more), eg. like this:
var input = document.getElementById('searchTextField');
var options = {
componentRestrictions: {country: 'au'}
};
autocomplete = new google.maps.places.Autocomplete(input, options);
For more information about advantages/disadvantages of both approaches see the docs (check section "Summary of classes") and choose the best approach for your needs.
I would also add to previous answer that there is a feature request in the public issue tracker to extend components restrictions for places autocomplete (make it similar to Geocoding API)
https://code.google.com/p/gmaps-api-issues/issues/detail?id=4433
If you are interested in this feature request please star it to express your interest and receive updates from Google.

Specify a Breeze entity default resource name with a parameter

I have an AngularJS app using breeze for data. The back end is OData v4.
I have a Customer entity and an Address entity defined in my metadata store.
The API defines the default endpoint for Address to be path/api/Customers({id})/Addresses
I am able to query a particular customer and get his/her address okay by using $expand.
However, if I edit or add a new Address for that customer (say, customer #42) and then call entityManager.saveChanges(), I need the POST/PATCH request to go to path/api/Customers(42)/Addresses.
Is there any way to configure my Address entity to accept a parameter in its defaultResourceName property?
You have a few options here - one is to call saveChanges and pass in some custom saveOptions -
http://www.getbreezenow.com/documentation/saving-changes
With this you could use
var so = new SaveOptions({ resourceName: entityId + "/Addresses" });
// null = 'all-pending-changes'; saveOptions is the 2nd parameter
myEntityManager.SaveChanges(addressEntities, so );
You will probably need to configure this for your needs.
The other possibility is to use breeze.ajaxPost to create a custom saveChanges method on your own on the client. This is more work intensive but allows you additional customization.

Categories