Google place autocomplete API with Laravel

ranjit2

Ranjeet Karki

Posted on July 20, 2022

Google place autocomplete API with Laravel

demo

In this post, I will show you how you can create a Google autocomplete address using Google Place API. You might have seen on some websites while filling out the address form it will automatically suggest the address and on clicking that address, it will fill in the rest of the fields like street line1, street line2, city, state, postcode etc.

So what do we need to follow this tutorial?

  • Setup laravel project: composer create-project laravel/laravel googleautocomplete
  • Install Guzzle: composer require guzzlehttp/guzzle
  • Valid Google API key
  • Check the Google Place Autocomplete API Docs: Google Place Autocomplete Api

Let's make a controller with index method that returns a form



php artisan make:controller GoogleAutocompleteController


Enter fullscreen mode Exit fullscreen mode

GoogleAutocompleteController.php



<?php

namespace App\Http\Controllers;

use Illuminate\View\View;
use Illuminate\Http\Request;

class GoogleAutocompleteController extends Controller
{
    public function index(): View
    {
        return view('form');
    }
}


Enter fullscreen mode Exit fullscreen mode

Inside resources/views/form.blade.php
I have created a simple form with bootstrap that has a street address field, city field, state field, postcode field, and country field.



@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Google autocomplete</div>
                    <div class="card-body">
                        <div class="form-group">
                            <label for="streetaddress">Street address</label>
                            <input type="text" class="form-control ui-widget autocomplete-google" id="street_address_1">
                        </div>

                        <div class="form-group">
                            <label for="streetaddress2">Street address 2</label>
                            <input type="text" class="form-control" id="street_address_2">
                        </div>

                        <div class="form-group">
                            <label for="city">City</label>
                            <input type="text" class="form-control" id="city">
                        </div>

                        <div class="form-group">
                            <label for="state">State</label>
                            <input type="text" class="form-control" id="state">
                        </div>

                        <div class="form-group">
                            <label for="postcode">Postcode</label>
                            <input type="text" class="form-control" id="postcode">
                        </div>

                        <div class="form-group">
                            <label for="country">Country</label>
                            <input type="text" class="form-control" id="country">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>



Enter fullscreen mode Exit fullscreen mode

In the above form, I have added a class ui-widget in the Street address field because I am using jQuery autocomplete library to pop up the address returned by Google API when the user actually starts tying the address in the Street address field. This class will enable our autocomplete.

Finally, we will register a route in web.php to view our form.



Route::get('/autocomplete',[GoogleAutocompleteController::class,'index']);



Enter fullscreen mode Exit fullscreen mode

Now, when you visit the /autocomplete url in the browser, you will see this form

preview image

Part 2
In this part, we will use jQuery autocomplete library and place API. Google place API will return the place id and based on the place id we will fill all the fields of the form.

Step1: go to jQuery autocomplete
copy jquery-ui.js and jquery-ui.css links and paste it in your app.blade.php

Now my layouts/app.blade.php looks like this



<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    <link rel="stylesheet" href="//code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
            <div class="container">
                <a class="navbar-brand" href="{{ url('/') }}">
                    {{ config('app.name', 'Laravel') }}
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <!-- Left Side Of Navbar -->
                    <ul class="navbar-nav me-auto">

                    </ul>

                    <!-- Right Side Of Navbar -->
                    <ul class="navbar-nav ms-auto">
                        <!-- Authentication Links -->
                        @guest
                            @if (Route::has('login'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
                                </li>
                            @endif

                            @if (Route::has('register'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
                                </li>
                            @endif
                        @else
                            <li class="nav-item dropdown">
                                <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                                    {{ Auth::user()->name }}
                                </a>

                                <div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                                    <a class="dropdown-item" href="{{ route('logout') }}"
                                       onclick="event.preventDefault();
                                                     document.getElementById('logout-form').submit();">
                                        {{ __('Logout') }}
                                    </a>

                                    <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
                                        @csrf
                                    </form>
                                </div>
                            </li>
                        @endguest
                    </ul>
                </div>
            </div>
        </nav>

        <main class="py-4">
            @yield('content')
            @yield('script')
        </main>
    </div>
</body>
</html>



Enter fullscreen mode Exit fullscreen mode

As you can see I have added @yield('script') above, which means everything that I wrapped within the script will be injected here. Later we will wrap javascript within @section('script')//..js code @endsection in form.blade.php

Step2: go to Google Place API
You can see types, You can restrict results from a Place Autocomplete request to be of a certain type by passing the types parameter. This parameter specifies a type or a type collection, as listed in Place Types. If nothing is specified, all types are returned.
We need address types

So, copy this URL and open your postman or browser, paste it and hit the send button.
https://maps.googleapis.com/maps/api/place/autocomplete/json?input= kathmandu nepal &types=address&key=YOUR_KEY

You should get a response like this:

api response

Note: we are interested in the place_id of the response. This is because with the help of place_id, we can get country, street address, postcode, city etc.

Step3: Open your config/services.php and set the key



'googlekey'=>[
    'key'=> env('GOOGLE_KEY', null),
 ],


Enter fullscreen mode Exit fullscreen mode

and in your .env file

GOOGLE_KEY=YOUR_GOOGLE_KEY

Step4: Now let's make one more route in web.php



Route::get('/placeid',[ GoogleAutocompleteController::class,'getPlaceId'])->name('placeid');


Enter fullscreen mode Exit fullscreen mode

and GoogleAutocompleteController.php looks like this



<?php

namespace App\Http\Controllers;

use Illuminate\View\View;
use Illuminate\Http\Request;

class GoogleAutocompleteController extends Controller
{

    public function index(): View
    {
        return view('form');
    }

    public function getPlaceId(Request $request)
    {
        //get user-typed address via Ajax request
    }

}


Enter fullscreen mode Exit fullscreen mode

Step5: In our form.blade.php let's add jQuery code to enable autocomplete dropdown, ajax request to send user typed address to our endpoint /placeId



 <script>
        $(document).ready(function() {
            $(".autocomplete-google").autocomplete({
                source: function(request, response) {
                    $.ajax({
                        url: '/placeid',
                        type: 'GET',
                        dataType: "json",
                        data: {
                            inputData: request.term,
                        },
                        success: function(data) {
                            response(data);
                        }
                    });
                },
            });
        });
  </script>



Enter fullscreen mode Exit fullscreen mode

Now our complete resources/form.blade.php looks like this



@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Google autocomplete</div>
                    <div class="card-body">
                        <div class="form-group">
                            <label for="streetaddress">Street address</label>
                            <input type="text" class="form-control ui-widget autocomplete-google" id="street_address_1">
                        </div>

                        <div class="form-group">
                            <label for="streetaddress2">Street address 2</label>
                            <input type="text" class="form-control" id="street_address_2">
                        </div>

                        <div class="form-group">
                            <label for="city">City</label>
                            <input type="text" class="form-control" id="city">
                        </div>

                        <div class="form-group">
                            <label for="state">State</label>
                            <input type="text" class="form-control" id="state">
                        </div>

                        <div class="form-group">
                            <label for="postcode">Postcode</label>
                            <input type="text" class="form-control" id="postcode">
                        </div>

                        <div class="form-group">
                            <label for="country">Country</label>
                            <input type="text" class="form-control" id="country">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

@section('script')
<script>
    $(document).ready(function() {
        $(".autocomplete-google").autocomplete({
            source: function(request, response) {
                $.ajax({
                    url: '/placeid',
                    type: 'GET',
                    dataType: "json",
                    data: {
                        inputData: request.term,
                    },
                    success: function(data) {
                        response(data);
                    }
                });
            },
        });
    });
</script>
@endsection


Enter fullscreen mode Exit fullscreen mode

Step 6: Now let's make a dedicated Handler class for the autocomplete. We could write all code in getPlaceId() of the GoogleAutocompleteController, but to clean up the code I think it is a good idea to move all your logic to another PHP class.
let's make AutocompleteHandler.php inside the Integration folder in the app directory.



<?php

namespace App\Integration;

use GuzzleHttp\Client;

class AutocompleteHandler
{

    public const BASE_URL = "https://maps.googleapis.com/maps/api/place";

    public string $key;

    public function __construct()
    {
        $this->key = config('services.googlekey.key');
    }

    public function placeId(string $address)
    {
       //
    }
}



Enter fullscreen mode Exit fullscreen mode

In the above code, I have set the base URL and key which we will use later. In above placeId(string $address) method we are receiving an address as a string parameter which we will receive from GoogleAutocompleteController getPlaceId() method as below.

Step7: Now let's inject AutocompleteHandler.php in GoogleAutocompleteController.php and pass address from getPlaceId() of GoogleAutocompleteController.php to placeId() of AutocompleteHandler.php

Now our GoogleAutocompleteController.php looks like this



<?php

namespace App\Http\Controllers;

use Illuminate\View\View;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use App\Integration\AutocompleteHandler;

class GoogleAutocompleteController extends Controller
{

    public $googleAutocomplete;

    public function __construct(AutocompleteHandler $googleAutocomplete)
    {
        $this->googleAutocomplete = $googleAutocomplete;
    }

    public function index(): View
    {
        return view('form');
    }

    public function getPlaceId(Request $request): JsonResponse
    {
        return $this->googleAutocomplete->placeId($request->inputData);
    }

}



Enter fullscreen mode Exit fullscreen mode

Above, We receive address as an inputData and we pass this inputData as an address parameter to placeId()

Step8: Now let's work on AutocompleteHandler.php. I will include the steps that we will perform here



<?php 
namespace App\Integration;

use GuzzleHttp\Client;

class AutocompleteHandler {

    public const BASE_URL = "https://maps.googleapis.com/maps/api/place";
    public string $key;

    public function __construct()
    {
        $this->key = config('services.googlekey.key');
    }

    public function placeId(string $address)
    {

        $url= "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=kathmandu&types=address&key=YOUR_API_KEY"
// build the readable url with http_build_query and sprintf()

        try {
            // step1: instantiate GuzzleHttp client
            // step2: hit the url
            // step3: get json response
            // step4: convert json to array
            // step5: loop over the predictions array of response
            // step6: and return place_id as id and description as label

        } catch (\Exception $e) {
            //catch error
        }
    }

}


Enter fullscreen mode Exit fullscreen mode

So our final AutocompleteHandler.php looks like this



<?php

namespace App\Integration;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use GuzzleHttp\Client;

class AutocompleteHandler
{

    public const BASE_URL = "https://maps.googleapis.com/maps/api/place";

    public string $key;

    public function __construct()
    {
        $this->key = config('services.googlekey.key');
    }

    public function placeId(string $address): JsonResponse
    {
        $url = sprintf(
            '%s/autocomplete/json?%s',
            self::BASE_URL,
            http_build_query([
                'input' => $address,
                'types' => 'address',
                'key' => $this->key,
            ])
        );
        try {
            $client = new Client();
            $response = $client->request('get', $url);
            $responseJson = $response->getBody()->getContents();
            $responseArray = json_decode($responseJson, true);
            return response()->json(collect($responseArray['predictions'])->map(
                fn ($value) =>
                [
                    'id' => $value['place_id'],
                    'label' => $value['description'],
                ]
            ));
        } catch (\Exception $e) {
            return response()->json([
                'error' => $e->getMessage(),
            ], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
}



Enter fullscreen mode Exit fullscreen mode

In the above, I have converted $responseArray to the collection with collect() and mapped over it to return place_id and description.

Now as you start typing in the form it will start suggesting the address to you as below.

autocomplete dropdown live search

Part 3
This is the last part of Google Place autocomplete. In this part, we will fill the rest of the form field when the user chooses one address from the dropdown.
Now, we need the place_id from the previous response, and if you hit this URL: https://maps.googleapis.com/maps/api/place/details/json?place_id=EhtOZXBhbCBUYXIsIEthdGhtYW5kdSwgTmVwYWwiLiosChQKEgk9yaxKzhjrORHvFQWGXi5RGhIUChIJv6p7MIoZ6zkR6rGN8Rt8E7U&key=YOUR_KEY
You will get your response in this format.

api response

So we are getting a result as a response and all the needed data such as street address, city, postcode etc are within the address_components

Step 1: In the above, we are returning place_id as the id, and now when the user clicks the address we will make another Ajax request to get all the details of the place based on place_id.
So, after the source, we can add select like the below



  select: function(event, ui) {
         var placeId = ui.item.id;
         console.log(placeId)        
   }


Enter fullscreen mode Exit fullscreen mode

So our jQuery code looks like this



<script>
        $(document).ready(function() {
            $(".autocomplete-google").autocomplete({
                source: function(request, response) {
                    $.ajax({
                        url: '/placeid',
                        type: 'GET',
                        dataType: "json",
                        data: {
                            inputData: request.term,
                        },
                        success: function(data) {
                            response(data);
                        }
                    });
                },
                select: function(event, ui) {
                    var placeId = ui.item.id;
                    console.log(placeId)

                }
            });
        });
 </script>


Enter fullscreen mode Exit fullscreen mode

If you click the selected address, it will return the place id in the console.

Step2: let's make an endpoint that accepts the place id and returns place details based on place id

In web.php



Route::get('address',[ GoogleAutocompleteController::class,'findAddressBasedOnPlaceId'])->name('address');


Enter fullscreen mode Exit fullscreen mode

So now web.php looks like this



<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\GoogleAutocompleteController;

Route::get('/autocomplete',[ GoogleAutocompleteController::class,'index']);
Route::get('/placeid',[ GoogleAutocompleteController::class,'getPlaceId'])->name('placeid');
Route::get('address',[ GoogleAutocompleteController::class,'findAddressBasedOnPlaceId'])->name('address');

Auth::routes();

Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');


Enter fullscreen mode Exit fullscreen mode

Step2: let's make this method in GoogleAutocompleteController.php



    public function findAddressBasedOnPlaceId(Request $request)
    {
        //get place_id via Ajax request when the user selects the address from dropdown suggestions
    }


Enter fullscreen mode Exit fullscreen mode

Step 3: From the above response returned from API, we can see that our data is in address_components and all responses may or may not return postcode, locality name, etc for that place_id. So we manually need to check if the required keys are present in the response or not in order to prevent the error on the page. for example, if a postcode is present in the response then we return the postcode, and so on. So, instead of writing an if-else statement for each key let's make a helper function that returns the required key if it is in the response

Now in AutocompleteHandler.php I will add these checks



    public function getDataFromAddressComponent(array $addressComponents, string $searchFor): ?string
    {
        return collect($addressComponents)->map(fn ($addressComponent) => collect($addressComponent['types'])->contains($searchFor) ? $addressComponent['long_name'] : null)->filter()->first();
    }


Enter fullscreen mode Exit fullscreen mode

Above, I am looping the $addressComponents and I am checking if we have $searchFor in that array. If true return something else return null. However, I have used the collection here.

Alternatively, we can do this



      foreach ($addressComponents as $address) {
            if (in_array($searchFor, $address['types'])) {
                return $address['long_name'];
            }
        }

       return null;



Enter fullscreen mode Exit fullscreen mode

Step4: In GoogleAutocompleteController.php, we will accept the place id from the Ajax request and pass it to addressBasedOnPlaceId() method of AutocompleteHandler.php, Which will return the details of the place



 public function findAddressBasedOnPlaceId(Request $request): JsonResponse
 {
      return $this->googleAutocomplete->addressBasedOnPlaceId($request->placeId);
 }


Enter fullscreen mode Exit fullscreen mode

Step5: Let's send placeId to findAddressBasedOnPlaceId() method via ajax

We will add getAddressDetails(placeId) in



 select: function(event, ui) {
       var placeId = ui.item.id;
        getAddressDetails(placeId);
  }


Enter fullscreen mode Exit fullscreen mode

getAddressDetails() function will make an ajax request to our endpoint /address
Now our, resource/form.blade.php looks like this



@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Google autocomplete</div>
                    <div class="card-body">
                        <div class="form-group">
                            <label for="streetaddress">Street number</label>
                            <input type="text" class="form-control ui-widget autocomplete-google" id="street_address_1">
                        </div>

                        <div class="form-group">
                            <label for="streetaddress2">Street address 2</label>
                            <input type="text" class="form-control" id="street_address_2">
                        </div>

                        <div class="form-group">
                            <label for="city">City</label>
                            <input type="text" class="form-control" id="city">
                        </div>

                        <div class="form-group">
                            <label for="state">State</label>
                            <input type="text" class="form-control" id="state">
                        </div>

                        <div class="form-group">
                            <label for="postcode">Postcode</label>
                            <input type="text" class="form-control" id="postcode">
                        </div>

                        <div class="form-group">
                            <label for="country">Country</label>
                            <input type="text" class="form-control" id="country">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

@section('script')
    <script>
        $(document).ready(function() {
            $(".autocomplete-google").autocomplete({
                source: function(request, response) {
                    $.ajax({
                        url: '/placeid',
                        type: 'GET',
                        dataType: "json",
                        data: {
                            inputData: request.term,
                        },
                        success: function(data) {
                            response(data);
                        }
                    });
                },
                select: function(event, ui) {
                    var placeId = ui.item.id;
                    getAddressDetails(placeId);
                }
            });
        });
        function getAddressDetails(placeId) {
        $.ajax({
            url: "/address",
            type: 'GET',
            dataType: "json",
            data: {
                placeId: placeId,
            },
            success: function(data) {
                $('#country').val(data.country);
                $('#city').val(data.locality);
                $('#postcode').val(data.postal_code);
                $('#state').val(data.state);
                $('#street_address_1').val(data.streetNumber);
                $('#street_address_2').val(data.streetName);
            },
            catch: function(error) {
                console.log('error');
            }
        });
    }
    </script>
@endsection


Enter fullscreen mode Exit fullscreen mode

In the above, on the success we get the result and we fill the form with country, city, postcode, state, etc, our API is yet not ready to return place details based on place ID.

Step6: In AutocompleteHandler.php we will make an addressBasedOnPlaceId() that will accept the place Id send from our findAddressBasedOnPlaceId() of GoogleAutocompleteController.php



public function addressBasedOnPlaceId(string $placeId): JsonResponse
{
    $url =   $url = // build the readable url with http_build_query and sprintf()
    https://maps.googleapis.com/maps/api/place/details/json?place_id=EhtOZXBhbCBUYXIsIEthdGhtYW5kdSwgTmVwYWwiLiosChQKEgk9yaxKzhjrORHvFQWGXi5RGhIUChIJv6p7MIoZ6zkR6rGN8Rt8E7U&key=YOUR_KEY
    );
    try {
        // step1: instantiate GuzzleHttp client
        // step2: hit the URL
        // step3: get JSON response
        // step4: Convert JSON to Array
        // step5: return required data such as street name, city, postcode, country, etc

    } catch (\Exception $e) {
        //catch error
    }
}


Enter fullscreen mode Exit fullscreen mode

Step7: The final AutocompleteHandler.php looks like this



<?php

namespace App\Integration;

use GuzzleHttp\Client;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

class AutocompleteHandler
{

    public const BASE_URL = "https://maps.googleapis.com/maps/api/place";

    private $key;
    public function __construct()
    {
        $this->key = config('services.googlekey.key');
    }

    public function getDataFromAddressComponent(array $addressComponents, string $searchFor): ?string
    {
        return collect($addressComponents)->map(fn ($addressComponent) => collect($addressComponent['types'])->contains($searchFor) ? $addressComponent['long_name'] : null)->filter()->first();
    }

    public function placeId(string $address): JsonResponse
    {
        $url = sprintf(
            '%s/autocomplete/json?%s',
            self::BASE_URL,
            http_build_query([
                'input' => $address,
                'types' => 'address',
                'key' => $this->key,
            ])
        );
        try {
            $client = new Client();
            $response = $client->request('get', $url);
            $responseJson = $response->getBody()->getContents();
            $responseArray = json_decode($responseJson, true);

            return response()->json(collect($responseArray['predictions'])->map(
                fn ($value) =>
                [
                    'id' => $value['place_id'],
                    'label' => $value['description'],
                ]
            ));
        } catch (\Exception $e) {
            return response()->json([
                'error' => $e->getMessage(),
            ], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function addressBasedOnPlaceId(string $placeId): JsonResponse
    {
        $url = sprintf(
            '%s/details/json?%s',
            self::BASE_URL,
            http_build_query([
                'place_id' => $placeId,
                'key' => $this->key,
            ])
        );
        try {
            $client = new Client();
            $response = $client->request('get', $url);
            $responseJson =  $response->getBody()->getContents();
            $responseArray = json_decode($responseJson, true);

            return response()->json([
                'streetNumber' => $this->getDataFromAddressComponent($responseArray['result']['address_components'], 'street_number'),
                'streetName' => $this->getDataFromAddressComponent($responseArray['result']['address_components'], 'route'),
                'locality' => $this->getDataFromAddressComponent($responseArray['result']['address_components'], 'locality'),
                'state' => $this->getDataFromAddressComponent($responseArray['result']['address_components'], 'administrative_area_level_1'),
                'administrative_area_level_2' => $this->getDataFromAddressComponent($responseArray['result']['address_components'], 'administrative_area_level_2'),
                'country' => $this->getDataFromAddressComponent($responseArray['result']['address_components'], 'country'),
                'postal_code' => $this->getDataFromAddressComponent($responseArray['result']['address_components'], 'postal_code')
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage(), 'exception' => get_class($e)], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
}



Enter fullscreen mode Exit fullscreen mode

So, we have returned the streetNumber, streetName, locality, state, postcode, and country in the response and we filled the rest of the form fields with these values.

👉 Get the code

💖 💪 🙅 🚩
ranjit2
Ranjeet Karki

Posted on July 20, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related