As part of a Laravel project that I’m working on, I wanted to setup a Vue component that would just give me a simple location search in an input box. It had to do a few things:

  • Return an object that had the formatted address, city and abbreviated state
  • Be slightly configurable for things like the labels and heading
  • Let the user select from a list of results
  • Not lag the entire browser on every keyup

Installation

I used https://github.com/alexpechkarev/google-maps

To install, just

composer require alexpechkarev/google-maps:1.0.7

Then register your providers

<code>'providers' => [
    ...
    'GoogleMaps\ServiceProvider\GoogleMapsServiceProvider',
]

'aliases' => [
    ...
    'GoogleMaps' => 'GoogleMaps\Facade\GoogleMapsFacade',
]</code>

Run php artisan vendor:publish --tag=googlemaps --force and then edit config/googlemaps.php with your API key from Google. You may have to allow a few location-based APIs in your Google dashboard, depending on what you’re using.

Usage

Some basic usage is below, but you can find more on the library’s Github.

$response = \GoogleMaps::load('geocoding')
        ->setParam (['address' =>'santa cruz'])
        ->get();

Great, so now we have some basic usage. But, we need to tie this into an endpoint and then access it when a user is typing.

First, let’s define how I want to use this from a parent Vue component.

<location-picker label="Location" v-model="location"></location-picker>

Ok, great. After adding the Location.vue to my components folder (or wherever you keep your Vue components), I’ve settled on this HTML markup:

<template>
    <div class="Location">
        <label class="label">{{ label }}</label>
        <p class="control">
            <input class="input" type="text" :placeholder="placeholder" @keyup="search" v-model="location.formatted"
                   ref="input" v-bind:value="value">
        </p>
        <span class="tag is-medium is-warning Location__tag" v-for="possibleLocation in possibleLocations"
              @click="selectLocation(possibleLocation)">
            {{ possibleLocation.formatted_address }}
        </span>
    </div>
</template>

On @keyup, we’ll need to run an axios call to our API to get the results for what the user inputs. However, we probably don’t want to run this for every s i n g l e k e y u p…since that would seriously spam the API (and Google!).

Using lodash, we can debounce the axios call, which basically throttles the requests to once every X seconds.

methods: {
            search: _.debounce(function () {
                axios.get('/api/v1/geosearch/' + this.location.formatted).then(response => {
                    this.possibleLocations = response.data.results;
                });
            }, 1000),
}

Now all we have left to do is create our route in Laravel to return some data given a user’s input.

Route::get('/api/v1/geosearch/{place}', function ($place) {
    return \GoogleMaps::load('geocoding')
        ->setParam(['address' => $place])
        ->get();
});

Now we should be getting data back! Great!

So, let’s use this data. I’m using Bulma’s tabs, but you can use whatever you’d like, obviously.

<span class="tag is-medium is-warning Location__tag" v-for="possibleLocation in possibleLocations"
    @click="selectLocation(possibleLocation)">
    {{ possibleLocation.formatted_address }}
</span>

This will give us our results in the form of some tabs like so:

And we’re done!

Leave some comments if you saw something I could have done differently, or have any questions!

One thought on “Setting up a Google location search in a Vue component in Laravel

  1. Have you ever thought about creating an ebook or guest authoring on other blogs?

    I have a blog centered on the same subjects you discuss and would really like to have you share
    some stories/information. I know my subscribers would
    appreciate your work. If you’re even remotely interested, feel free to send me an e-mail.

Leave a Reply

Your email address will not be published. Required fields are marked *