I want to create a contact form with 2 sections.

The first section includes an address field.

I have a repository of 100,000 addresses in CSV format.

I need to import all addresses into the address field. Also i need to have an autocomplete attribut for the address field.

So when you type the first characters (4) of an address in this field, the corresponding addresses appear.

The second section corresponds to the rest of the form. Fields: name, first name, message and send button.

Remark : the second section appear only after the selection of an address.

My concern is how to import my addresses with my CSV file and link the addresses of the file to the address form field + add autocomplete attribute.

I'm using gravity form as form plugin. So if you have an idea how to achieve that with gravity form or an other plugin. it will be great.

Example of what i'm looking for. Below a field called tags with values (in my case the 100000 addresses) as you can see, i need to be able to selecta value from a pre-populated list of values.

enter image description here

Thank you in advance for your answers.


1 Answer 1


I don't have gravity forms but I experience in creating autocomplete fields using data from DB, csv, apis and so one.

The concept remains the same, it's just how you call and receive the date that changes, depending in your source.

Starting with my csv, I looked for country names to stay as close to the address field meaning.
The csv structure is this

AD 42.546245 1.601554 Andorra
AE 23.424076 53.847818 United Arab Emirates
AF 33.93911 67.709953 Afghanistan

And so on...

Because I don't have gravity form and I have no idea how it works, I made a simple example that will work with a input field, so no matter what you use it will work.
You will need to play around with css because you may not have the same containers as in my example.

Our form will consist of only one input field, out address, and a submit button.
The example focuses on the address field and its outcomplete feature.

<form class="gravity">
    <div class="input-wrap">
            <span class="label">Address:</span>
            <div class="ajax-wrap">
                <input type="text" name="address">
    <div class="input-wrap submit">
        <button type="submit">Send</button>

Some basic css to give structure to everything

.gravity {
    padding: 15px; 

.gravity .input-wrap:not(:last-child) {
    margin-bottom: 15px;

.gravity .input-wrap .ajax-wrap {
    position: relative;

.gravity .input-wrap .ajax-wrap .address-ajax-results {
    position: absolute;
    top: 100%;
    left: 0;
    border: 1px solid #767676;
    background-color: #fff;
    width: 100%;

.gravity .input-wrap .ajax-wrap p.address-ajax-results {
    padding: 10px;
    font-weight: 700;
    margin: 0;

.gravity .input-wrap .ajax-wrap ul.address-ajax-results {
    max-height: 200px;
    overflow-x: hidden;
    overflow-y: auto;

.gravity .input-wrap .ajax-wrap ul.address-ajax-results li:not(:last-child) {
    border-bottom: 1px solid #767676;

.gravity .input-wrap .ajax-wrap ul.address-ajax-results li button {
    padding: 5px 10px;
    display: block;
    width: 100%;
    text-align: left;

.gravity .input-wrap .ajax-wrap ul.address-ajax-results li button:hover {
    background-color: #eee;

.gravity .input-wrap.submit button {
    display: block;
    background-color: #69AFE5;
    color: #fff;
    border-radius: 5px;
    padding: 5px 10px;
    width: 100%;
    font-weight: 700;

The client side logic for the request and output of our addresses

($ => {
    // timer for delaying ajax request for addresses
    let timerBeforeCheck;

    // how long to wait, in milliseconds, before the ajax request
    const timerDelay = 750;

    // minimum amount of charcters for a ajax request
    const minChar = 2;

    // our field target,
    // Change it to your needs
    const addressFieldTarget = '.gravity [name="address"]';

    $(addressFieldTarget).on('keyup paste', e => {
        // clear previous timer

        // the current element, address input
        const $this = $(e.currentTarget);

        // if minimum amount of charcters for a ajax request not met
        // remove previous results and stop
        if ($this.val().length < minChar) {
            // clear previous results

        // start timer, after it finished (based on timerDelay)
        // send ajax request for the csv data
        timerBeforeCheck = setTimeout(() => {
            // clear previous results

            const userInput = $this.val();

                method: 'post',
                url: 'http://localhost/timber/wp-admin/admin-ajax.php',
                dataType: 'json',
                data: {
                    action: 'bt_get_form_addresses',
                    address: userInput
                success: res => {
                    // if no results found display message
                    if (!res.length) $this.after('<p class="address-ajax-results">No results found.</p>');
                    else { // results found, build a results list a user can select from
                        let $list = '';
                        $list += '<ul class="address-ajax-results">';

                        res.map(address => {
                            $list += '<li>';
                            $list +=   '<button type="button">' + address + '</button>';
                            $list += '</li>';

                        $list += '</ul>';

        }, timerDelay);

    // show the addresses ajax response html input focus
    // if input already has value
    // that means that we already have the ajax response html
    $(addressFieldTarget).on('click', e => {
        // prevent out global document click close from triggering
        if ($(e.currentTarget).val().length < minChar) return;

    // close the ajax results on any click on page
    $(document).on('click', () => {

    // on addresses ajax response select
    // populate the address input
    $(document).on('click', '.address-ajax-results button', e => {
        // prevent out global document click close from triggering

        // populate our input

        // close ajax results

The server side logic that is responsible for retrieving the data from out csv file based on the user input.
My csv file is located in the root of the theme and named countries.csv, the php code is located in functions.php.
So to read the csv file we can do this fopen(__DIR__ . '/countries.csv', 'r').

// we use this two actions in order to make our ajax request
// available for both logged and not logged in users
add_action('wp_ajax_bt_get_form_addresses', 'bt_get_form_addresses');
add_action('wp_ajax_nopriv_bt_get_form_addresses', 'bt_get_form_addresses');
function bt_get_form_addresses () {
    // results to return
    $found = [];

    // try to open the csv
    if (($handle = fopen(__DIR__ . '/countries.csv', 'r')) !== FALSE) {
        // sanitize and check if the user value has anything
        if (!empty($address = filter_input(INPUT_POST, 'address', FILTER_SANITIZE_STRING))) {
            // start looping each csv row
            while (($data = fgetcsv($handle, 1000, ',')) !== FALSE) {
                // if our csv column value doesn't start with X
                // in this case the user value
                // continue to next csv row
                if (!preg_match('/^' . $address . '/i', $data[3])) continue;

                // add the found value to our results to return
                $found[] = $data[3];

    // because or ajax request expects json format
    // we do the following
    echo json_encode($found);

    // this prevents any other code from executing

You can just copy/paste the code and it will work.
Just remember to create the csv file and follow the structure.
Here is an example on how it works on my local environment.

enter image description here

  • nice example helps me a lot. Could you please drop a cv file link Commented Sep 10, 2021 at 9:47
  • 1
    @RajneeshTiwari This is not the original of course, I just found some csv online (don't rememebr where), copy pasted it to my google sheets and downloaded it as .csv file. This is the link Commented Sep 11, 2021 at 8:17
  • Thank you for your kind reply, you deserve a rating. Commented Sep 11, 2021 at 8:36
  • Thanks @Buttered_Toast for the reply is it possible to have a private chat with you?
    – Samuel
    Commented Sep 17, 2021 at 15:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.