Skip to content

Commit 51923d0

Browse files
committed
Refactor Places Autocomplete component and update README
- Enhanced the PlacesAutocompleteComponent with additional properties for better configuration. - Updated the Blade view to utilize the new properties and improved event handling. - Added a GIF demo to the README and expanded documentation for clarity.
1 parent 5cc065e commit 51923d0

File tree

4 files changed

+211
-42
lines changed

4 files changed

+211
-42
lines changed

README.md

Lines changed: 127 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,145 @@
1-
# laravel-places-autocomplete
1+
# Places Autocomplete for Laravel
22

3-
Easily integrate the Places (New) Autocomplete - JavaScript library into Laravel Blade views. Provides a user-friendly way to search for and retrieve detailed address information in any web application.
3+
[![GitHub Stars](https://img.shields.io/github/stars/alexpechkarev/laravel-places-autocomplete.svg?style=flat-square)](https://github.com/alexpechkarev/laravel-places-autocomplete/stargazers)
4+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/alexpechkarev/laravel-places-autocomplete.svg?style=flat-square)](https://packagist.org/packages/alexpechkarev/laravel-places-autocomplete)
5+
[![Total Downloads](https://img.shields.io/packagist/dt/alexpechkarev/laravel-places-autocomplete.svg?style=flat-square)](https://packagist.org/packages/alexpechkarev/laravel-places-autocomplete)
6+
[![GitHub License](https://img.shields.io/github/license/alexpechkarev/laravel-places-autocomplete.svg?style=flat-square)](https://github.com/alexpechkarev/laravel-places-autocomplete/blob/master/LICENSE)
7+
8+
A Laravel package that provides a simple Blade component to integrate the Google Places Autocomplete functionality into your application with minimal setup.
9+
10+
It handles API loading, session tokens for cost-effective usage, and fetching place details, allowing you to focus on building your application.
11+
12+
## Features
13+
14+
- **Simple Integration:** Add address autocomplete to any form with a single Blade component.
15+
- **Cost-Effective:** Automatically handles session tokens to reduce Google API costs.
16+
- **Customizable:** Configure the component's behavior through an options array.
17+
- **Event-Driven:** Dispatches a custom event with the selected place data for easy handling in your frontend JavaScript.
18+
19+
## Live Demo
20+
21+
See a comprehensive live demo of the underlying JavaScript library in action: [pacservice.pages.dev](https://pacservice.pages.dev/)
22+
23+
<img src="places-autocomplete-js.gif" alt="A video demonstrating the Places Autocomplete JavaScript component in action, showing address suggestions and selection.">
24+
25+
## Requirements
26+
27+
- Laravel 9.x or higher
28+
- A Google Maps API Key with the **Places API** enabled. You can get one from the [Google Cloud Console](https://console.cloud.google.com/google/maps-apis).
429

530
## Installation
6-
Install the package via Composer:
31+
32+
You can install the package via Composer:
733

834
```bash
935
composer require alexpechkarev/laravel-places-autocomplete
1036
```
1137

38+
## Configuration
39+
40+
1. Publish the configuration file. This will create a `config/places-autocomplete.php` file where you can set default options. The view file will be published to `resources/views/vendor/places-autocomplete` and the JavaScript files to `public/vendor/places-autocomplete/`.
41+
42+
```bash
43+
php artisan vendor:publish --provider="PlacesAutocomplete\PlacesAutocompleteServiceProvider"
44+
```
45+
46+
2. Add your Google Maps API key to your `.env` file. This is a required step.
47+
48+
```dotenv
49+
// filepath: .env
50+
GOOGLE_MAPS_API_KEY="YOUR_API_KEY_HERE"
51+
```
52+
1253
## Usage
13-
In your Blade view, you can use the `<x-places-autocomplete>` component to render the autocomplete input field. You can pass options as an array to customize the behavior of the component.
54+
55+
### 1. Add the Component
56+
57+
Use the `<x-places-autocomplete>` component in your Blade views. Because the component's root element has a dynamically generated ID, the recommended approach is to wrap it in your own `div` with a stable ID. This makes it easy to target with JavaScript.
58+
1459
```php
15-
<x-places-autocomplete
16-
:options="['placeholder' => 'Start typing your address...', 'clear_input' => false, 'debounce' => 100]" />
17-
60+
// filepath: resources/views/your-form.blade.php
61+
<form>
62+
<label for="address">Address</label>
63+
64+
{{-- Wrap the component in a div with a known ID --}}
65+
<div id="address-wrapper">
66+
<x-places-autocomplete
67+
root-div-id="address-wrapper"
68+
:options="[
69+
'placeholder' => 'Start typing your address...',
70+
]"
71+
/>
72+
</div>
73+
74+
{{-- Other fields to be populated by JavaScript --}}
75+
<div class="mt-4">
76+
<label for="city">City</label>
77+
<input type="text" id="city" name="city" class="form-control">
78+
</div>
79+
<div>
80+
<label for="postcode">Postcode</label>
81+
<input type="text" id="postcode" name="postcode" class="form-control">
82+
</div>
83+
</form>
1884
```
1985

86+
### 2. Handle the Response
87+
88+
When a user selects an address, the component dispatches a `pac-response` custom event on its root `div`. You can listen for this event to receive the place data.
89+
90+
Add the following JavaScript to your application.
91+
92+
```javascript
93+
// filepath: resources/js/app.js
94+
document.addEventListener("DOMContentLoaded", function () {
95+
// Listen for the custom event emitted by the PlacesAutocomplete component
96+
document
97+
.getElementById("address-wrapper")
98+
.addEventListener("pac-response", function (event) {
99+
const placeDetails = event.detail;
100+
//console.log('Place Selected:', placeDetails);
101+
102+
// Populate other fields based on the selected place details
103+
if (placeDetails.addressComponents) {
104+
placeDetails.addressComponents.forEach((component) => {
105+
if (component.types.includes("postal_town")) {
106+
document.getElementById("city").value = component.longText;
107+
}
108+
if (component.types.includes("postal_code")) {
109+
document.getElementById("postcode").value = component.longText;
110+
}
111+
});
112+
}
113+
});
114+
115+
// Handle errors from the PlacesAutocomplete component
116+
document
117+
.getElementById("address-wrapper")
118+
.addEventListener("pac-error", function (event) {
119+
console.error("Autocomplete Error:", event.detail);
120+
});
121+
});
122+
```
123+
124+
## Component Options
125+
126+
You can customize the component by passing an `:options` array. These options are passed to the underlying [places-autocomplete-js](https://github.com/alexpechkarev/places-autocomplete-js) library.
127+
128+
| Option | Type | Description |
129+
| ------------- | ------- | -------------------------------------------------------------- |
130+
| `placeholder` | string | Placeholder text for the input field. |
131+
| `debounce` | integer | Delay in milliseconds before sending a request (default: 100). |
132+
| `clear_input` | boolean | Whether to clear the input after selection. |
133+
| `language` | string | The language code for results (e.g., 'en-GB'). |
134+
135+
For a full list of options, please refer to the [JavaScript library's documentation](https://github.com/alexpechkarev/places-autocomplete-js?tab=readme-ov-file#configuration).
136+
137+
**Note:** The `name` attribute of the generated `<input>` is not currently configurable. The input's data will not be submitted with a standard form post; you must use JavaScript to handle the `pac-response` event and populate your form fields as shown in the example above.
20138

21139
## Support
22140

23-
[Please open an issue on GitHub](https://github.com/alexpechkarev/laravel-places-autocomplete/issues)
141+
If you encounter any issues or have questions, please [open an issue on GitHub](https://github.com/alexpechkarev/laravel-places-autocomplete/issues).
24142

25143
## License
26144

27-
Collection of Google Maps API Web Services for Laravel is released under the MIT License. See the bundled
28-
[LICENSE](https://github.com/alexpechkarev/laravel-places-autocomplete/blob/master/LICENSE)
29-
file for details.
145+
This package is open-source software licensed under the [MIT license](https://github.com/alexpechkarev/laravel-places-autocomplete/blob/master/LICENSE).

places-autocomplete-js.gif

569 KB
Loading
Lines changed: 80 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,96 @@
11
<?php
22

3-
namespace PlacesAutocomplete;
3+
namespace PlacesAutocomplete\View\Components;
4+
5+
use Illuminate\View\Component;
6+
use \Illuminate\Support\Str;
47

5-
use Illuminate\Support\Facades\Blade;
6-
use Illuminate\Support\ServiceProvider;
7-
use PlacesAutocomplete\View\Components\PlacesAutocompleteComponent;
88

99
/**
10-
* Service provider for the Places Autocomplete package.
10+
* Class PlacesAutocompleteComponent
11+
*
12+
* A Blade component for integrating Google Places Autocomplete.
13+
*
14+
* @package PlacesAutocomplete\View\Components
1115
*/
12-
class PlacesAutocompleteServiceProvider extends ServiceProvider
16+
17+
class PlacesAutocompleteComponent extends Component
1318
{
19+
public string $containerId; // Unique ID for the container element
20+
public string $rootDivId; // ID for the root div element
21+
public string $googleMapsApiKey; // Google Maps API key for Places Autocomplete
22+
public array $options; // Options for the Places Autocomplete component
23+
public array $requestParams; // Request parameters for the Places Autocomplete component
24+
public array $fetchFields; // Fetch fields for the Places Autocomplete component
25+
public bool $loadScriptTag; // New option to control script loading
26+
27+
1428
/**
15-
* Register any application services.
29+
* Class constructor.
30+
*
31+
* @param string $containerId
32+
* @param string $rootDivId
33+
* @param string $googleMapsApiKey
34+
* @param array $options
35+
* @param array $requestParams
36+
* @param array $fetchFields
37+
* @param bool $loadScriptTag
1638
*/
17-
public function register(): void {}
39+
public function __construct(
40+
string $containerId = 'pac_container',
41+
string $rootDivId = 'places-autocomplete-root',
42+
string $googleMapsApiKey = '',
43+
array $options = [],
44+
array $requestParams = [],
45+
array $fetchFields = [],
46+
bool $loadScriptTag = true // Default to true
47+
) {
48+
49+
// Ensure unique ID
50+
$this->containerId = $containerId . '-' . Str::random(5);
51+
52+
$this->rootDivId = $rootDivId;
53+
// Set Google Maps API key, options, request parameters, fetch fields, and script loading option
54+
$this->googleMapsApiKey = !empty($googleMapsApiKey) ? $googleMapsApiKey : config('places_autocomplete.google_maps_api_key');
55+
// Merge with default options, request parameters, and fetch fields from config
56+
$this->options = array_merge(config('places_autocomplete.options', []), $options);
57+
58+
// Request parameters and fetch fields are merged with defaults from config
59+
// This allows users to override them when using the component in their Blade templates
60+
$this->requestParams = array_merge(config('places_autocomplete.request_params', []), $requestParams);
61+
62+
// Fetch fields are merged with defaults from config
63+
// This allows users to override them when using the component in their Blade templates
64+
// Default fetch fields include 'formattedAddress' and 'addressComponents'
65+
$this->fetchFields = array_merge(config('places_autocomplete.fetch_fields', ['formattedAddress', 'addressComponents']), $fetchFields);
66+
67+
// Set the loadScriptTag property to control whether the script tag is loaded
68+
// This allows users to choose whether to load the Google Maps script tag automatically
69+
$this->loadScriptTag = $loadScriptTag;
70+
71+
// Validate that the Google Maps API key is set
72+
// If not set, throw an exception to inform the user
73+
if (empty($this->googleMapsApiKey)) {
74+
throw new \InvalidArgumentException('Google Maps API key is not configured. Please set it in your .env file or config/places_autocomplete.php');
75+
}
76+
}
1877

1978
/**
20-
* Bootstrap any application services.
79+
* Render the component view.
80+
*
81+
* @return void
2182
*/
22-
public function boot(): void
83+
public function render()
2384
{
24-
// Publishing the configuration file
25-
$this->publishes([
26-
__DIR__ . '/config/places_autocomplete.php' => config_path('places_autocomplete.php'),
27-
], 'places-autocomplete');
28-
29-
// Publishing the JavaScript assets
30-
$this->publishes([
31-
__DIR__ . '/js' => public_path('vendor/places-autocomplete'),
32-
], 'places-autocomplete');
33-
34-
// Publishing the view files
35-
$this->publishes([
36-
__DIR__ . '/views' => resource_path('views/vendor/places-autocomplete'),
85+
return view('vendor.places-autocomplete.places-autocomplete', [
86+
'containerId' => $this->containerId,
87+
'rootDivId' => $this->rootDivId,
88+
'googleMapsApiKey' => $this->googleMapsApiKey,
89+
'options' => $this->options,
90+
'requestParams' => $this->requestParams,
91+
'fetchFields' => $this->fetchFields,
92+
'loadScriptTag' => $this->loadScriptTag,
3793
]);
38-
39-
// Registering the Blade component
40-
// This allows the component to be used in Blade templates
41-
// The component can be used with the syntax: <x-places-autocomplete />
42-
// The component will be rendered using the PlacesAutocompleteComponent class
43-
Blade::component('places-autocomplete', PlacesAutocompleteComponent::class);
4494
}
4595
}
96+
// End of PlacesAutocompleteComponent class

src/views/places-autocomplete.blade.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
{{-- This component initializes the PlacesAutocomplete library with the provided options and parameters. --}}
66
@props([
77
'containerId' => 'places-autocomplete',
8+
'rootDivId' => 'places-autocomplete-root',
89
'googleMapsApiKey' => config('places_autocomplete.google_maps_api_key'),
910
'options' => [],
1011
'requestParams' => [],
1112
'fetchFields' => [],
1213
'loadScriptTag' => true,
14+
'rootDivId' => 'places-autocomplete-root',
1315
])
1416

1517
{{-- Ensure the container ID is valid --}}
@@ -44,8 +46,8 @@
4446
const event = new CustomEvent('pac-response', {
4547
detail: placeDetails
4648
});
47-
document.getElementById('{{ $containerId }}').dispatchEvent(event);
48-
console.log('Place Selected (from Blade component):', placeDetails);
49+
document.getElementById('{{ $rootDivId }}').dispatchEvent(event);
50+
//console.log('Place Selected (from Blade component):', placeDetails);
4951
// Or define global callback names that users can implement
5052
// if (typeof window.handlePacResponse_{{ str_replace('-', '_', $containerId) }} === 'function') {
5153
// window.handlePacResponse_{{ str_replace('-', '_', $containerId) }}(placeDetails);

0 commit comments

Comments
 (0)