CRUD
CRUD copied to clipboard
[4.1][Package / Custom Field] Input Address with Google API / Google Maps
Summary
Creates an address form composed by:
- an autocomplete field based on Google Places API
- several other fields, choosen by the user, that will contain the components of the address
The fields will be filled automatically
Preview
Usage
$this->crud->addField([
'name' => 'address',
'label' => 'Indirizzo',
'type' => 'address_form_google',
'google_api_key' => env('GOOGLE_API_KEY'),
'components' => [
'COMPONENT' => [
'name' => 'address_line_1',
'label' => 'Via',
'type' => 'long_name', // Optional
],
// Other components
],
]);
This field needs a Google API Key that can be retrived here
The components that can be used are:
- 'route'
- 'street_number'
- 'postal_code'
- 'locality'
- 'administrative_area_level_1'
- 'administrative_area_level_2'
- 'country'
so a complete field would look like this:
$this->crud->addField([
'name' => 'address',
'label' => 'Indirizzo',
'type' => 'address_form_google',
'google_api_key' => env('GOOGLE_API_KEY'),
'components' => [
'route' => [
'name' => 'address_line_1',
'label' => 'Via',
'type' => 'long_name',
],
'street_number' => [
'name' => 'address_line_2',
'label' => 'Civico',
'type' => 'short_name',
],
'postal_code' => [
'name' => 'postal_code',
'label' => 'CAP',
'type' => 'short_name',
],
'locality' => [
'name' => 'city',
'label' => 'Città',
'type' => 'long_name',
],
'administrative_area_level_1' => [
'name' => 'region',
'label' => 'Regione',
'type' => 'long_name',
],
'administrative_area_level_2' => [
'name' => 'province',
'label' => 'Provincia',
'type' => 'short_name',
],
'country' => [
'name' => 'country',
'label' => 'Nazione',
'type' => 'short_name',
],
],
]);
the 'type' attribute is optional and can be set to 'short_name' or 'long_name'. The default value is 'long_name'.
Each component needs a column in the table. The autocomplete field is not stored so it doesn't need a column in the table.
A complete migration would look like this:
public function up()
{
Schema::create('addresses', function (Blueprint $table) {
$table->increments('id');
$table->string('address_line_1');
$table->string('address_line_2');
$table->string('city');
$table->string('region');
$table->string('province');
$table->string('postal_code');
$table->string('country');
$table->timestamps();
});
}
All the fields can be validated with their own rules like every standard field.
Thank you @OwenMelbz :smile: I will implement the changes you suggested!
About the API key, do you mean using the env() variable directly in the api call like this
<script src="https://maps.googleapis.com/maps/api/js?key={{ $env('GOOGLE_API_KEY') }} ...></script>
instead of
<script src="https://maps.googleapis.com/maps/api/js?key={{ $field['google_api_key'] }} ...></script>
and eliminate the google_api_key attribute inside the field?
Or I can check if the google_api_key exists in the field attribute, if not I check if it exists in the .env file.
Enhancement
I have to admit that I was inspired by the address field you created using Agolia Places ( congratulations btw :grin: ) but I needed something more complex. I first tried with Agolia Places but the Open Street Map isn't as complete as Google Maps and I was really disappointed when it couldn't find office address!
I was thinking to enhance my address field giving the possibility to be used like the address field that already exists but using Google Places API. It would look like this
BASIC FIELD
$this->crud->addField([
'name' => 'address',
'label' => 'Address',
'type' => 'address_form_google',
// optional
'store_as_json' => true
]);
ADVANCED FIELD
$this->crud->addField([
'name' => 'address',
'label' => 'Address',
'type' => 'address_form_google',
'components' => [
'COMPONENT' => [
'name' => 'address_line_1',
'label' => 'Street',
'type' => 'long_name', // Optional
],
// Other components
],
]);
What do you think about?
Is this possible to get location from our location or device like using HTML5 instead typing specific address? Would be useful if that happens. :)
@M4rk3tt0 your suggested enhancement (both basic and advanced) sound PERFECT to me. I like the "components" name for that attribute. I also like the idea of also being able to define the Google API key in an environment variable. Could we call the field "google_address"? I'm thinking that we'll also call the other one "algolia_address" and in time we'll phase out the simple "address" one.
@elraghifary I think that might be overkill. CRUDs are usually for inserting a lot of information, so A LOT of it won't be about your current location, but some other location. So geolocation might end up being more annoying that useful, in most cases.
Cheers guys!
@M4rk3tt0 Im thinking of something waterfall like allowing multiple locations, for ultimate flexibility for the user so maybe like
$googleApiKey = isset( $field['google_api_key'] ) ? $field['google_api_key'] : ( config('backpack.google_api_key', env('GOOGLE_API_KEY', null) );
<script src="https://maps.googleapis.com/maps/api/js?key={{ $googleApiKey }} ...></script>
So that way
- A user can pass in a api key if they want, otherwise
- It can pull it from their config (this might pull from their env file, and helps users who have diff api keys for different services)
- If its not found in the config, it will try find it in the env variables
- else I imagine google will just 400 error.
Then they can set it globally.
What do you think to that?
But I definitely like the idea of a more complex one, maybe we could merge the 2 features? create something like 'provider' => 'google' //others algolia
this way would allow more flexibility for users? and would also mean its backwards compatible if we keep the default as Algolia and just document it nicely?
@elraghifary thats a nice idea :) Yes its possible to get an estimated lat / long from the HTML geolocation function similar to navigator.geolocation.getCurrentPosition(callBack);
I don't think this fits in with Backpacks current roadmap, but as a community member you're more than welcome to submit PR with this functionality, or maybe liaise with @M4rk3tt0 to see if its something he wants to expand his PR with? maybe another option! 'enable_html5_location' => true
etc
@tabacitu I'm glad you like it! I will work on it as soon as I can :smile:
@OwenMelbz Yes that makes sense, I will implement the api key the way you suggested. We can definitely merge the two address fields together when they are ready.
@elraghifary It is possible to get the location using HTML5 and use the Reverse Geocoding of Google Geolocation API to get the address but it would be only an estimate. The user would have to fill the fields manually because the address would be wrong. You can try if you want. Get an API KEY and send a get request the url that you find HERE replacing the latitude and longitude with the one you get from HTML5.
The geolocation could be useful to reduce Google Places API search area.
Recommend adding an option to change the autocomplete search (e.g. 'establishment').
@tabacitu What about merging this?
Possible to add country restriction option in the address_google
CRUD options?
// Set initial restrict to the greater list of countries.
$autocomplete.setComponentRestrictions(
{'country': ['us', 'pr', 'vi', 'gu', 'mp']}
);
There are some good ideas that we can extract from here to apply in our google_address
field, but I think it's time to put this 8 year issue behind us.
Thanks everyone that worked on this, and sorry it didn't get merged.
Cheers