Demonstração da Address Validation

Testar a Address Validation

Use este exemplo para testar a API Address Validation com qualquer endereço de uma região com suporte. A demonstração usa os componentes do endereço como entrada e mostra a resposta de validação abaixo. Para analisar um endereço não estruturado, insira o endereço completo no campo Endereço 1. Selecione exemplos de endereços no menu suspenso na parte de cima do formulário.

TypeScript

// DOM Refs
const addressForm = document.getElementById('address-form');
const validateButton = document.getElementById('validate-button');
const clearFormButton = document.getElementById('clear-form-button');
const resultDisplay = document.getElementById('result-display');
const loadingText = document.getElementById('loading-text');
// Input field refs
const streetAddress1Input = document.getElementById(
    'street-address-1'
) as HTMLInputElement;
const streetAddress2Input = document.getElementById(
    'street-address-2'
) as HTMLInputElement;
const cityInput = document.getElementById('city') as HTMLInputElement;
const stateInput = document.getElementById('state') as HTMLInputElement;
const zipCodeInput = document.getElementById('zip-code') as HTMLInputElement;
const regionSelect = document.getElementById(
    'region-select'
) as HTMLSelectElement;
const exampleSelect = document.getElementById(
    'example-select'
) as HTMLSelectElement;

// Core Initialization
async function init() {
    // Load the Address Validation library.
    await google.maps.importLibrary('addressValidation');
    // Set event listeners
    addressForm!.addEventListener('submit', handleValidationSubmit);
    exampleSelect!.addEventListener('change', handleExampleSelectChange);
    clearFormButton!.addEventListener('click', handleClearForm);
}

// Validation Handler
async function handleValidationSubmit(event) {
    event.preventDefault(); // Prevent default form submission
    resultDisplay!.textContent = 'Validating...'; // Clear previous results

    // Validate the address
    try {
        //prettier-ignore
        //@ts-ignore
        const result = await google.maps.addressValidation.AddressValidation.fetchAddressValidation(
                {
                    address: {
                        regionCode: regionSelect!.value.trim(),
                        languageCode: 'en',
                        addressLines: [
                            streetAddress1Input!.value.trim(),
                            streetAddress2Input!.value.trim(),
                        ].filter((line) => line), // Filter out empty lines
                        locality: cityInput!.value.trim(),
                        administrativeArea: stateInput!.value.trim(),
                        postalCode: zipCodeInput!.value.trim(),
                    },
                }
            );

        resultDisplay!.textContent =
            'Verdict summary\n================\n' +
            `Formatted address: ${result.address.formattedAddress}\n` +
            `Entered: ${result.verdict.inputGranularity}\n` +
            `Validated: ${result.verdict.validationGranularity}\n` +
            `Geocoded: ${result.verdict.geocodeGranularity}\n` +
            `Possible next action: ${result.verdict.possibleNextAction}\n\n` +
            `${getVerdictMessage(result.verdict, 'addressComplete')}\n` +
            `${getVerdictMessage(result.verdict, 'hasUnconfirmedComponents')}\n` +
            `${getVerdictMessage(result.verdict, 'hasInferredComponents')}\n` +
            `${getVerdictMessage(result.verdict, 'hasReplacedComponents')}\n\n` +
            `Raw JSON response\n=================\n` +
            JSON.stringify(result, null, '  ');
    } catch (error) {
        console.error('Validation failed:', error);
        if (error instanceof Error) {
            resultDisplay!.textContent = `Error: ${error.message}`;
        }
    }
}

// Verdict messages
const verdictMessages = {
    addressComplete: {
        trueMessage:
            '- The API found no unresolved, unexpected, or missing address elements.',
        falseMessage:
            '- At least one address element is unresolved, unexpected, or missing.',
    },
    hasUnconfirmedComponents: {
        trueMessage: "- The API can't confirm at least one address component.",
        falseMessage: '- The API confirmed all address components.',
    },
    hasInferredComponents: {
        trueMessage:
            '- The API inferred (added) at least one address component.',
        falseMessage: '- The API did not infer (add) any address components.',
    },
    hasReplacedComponents: {
        trueMessage: '- The API replaced at least one address component.',
        falseMessage: '- The API did not replace any address components.',
    },
};

// Helper function to get the verdict message for a given verdict key
function getVerdictMessage(verdict, key) {
    if (!verdict || !verdictMessages[key]) return 'Unknown';
    return verdict[key]
        ? verdictMessages[key].trueMessage
        : verdictMessages[key].falseMessage;
}

// Handler for Dropdown Change
function handleExampleSelectChange(event) {
    const selectedValue = event.target.value;
    if (selectedValue && examples[selectedValue]) {
        populateAddressFields(examples[selectedValue]);
    } else if (!selectedValue) {
        populateAddressFields(null); // Pass null to clear fields
    }
}

// Clear Form Handler
function handleClearForm() {
    streetAddress1Input!.value = '';
    streetAddress2Input!.value = '';
    cityInput!.value = '';
    stateInput!.value = '';
    zipCodeInput!.value = '';
    regionSelect!.value = '';
    exampleSelect!.value = '';
    resultDisplay!.textContent = 'Result will appear here...';
    console.log('Cleared form');
}

// Example Address Data
const examples = {
    google: {
        streetAddress1: '1600 Amphitheatre Parkway',
        streetAddress2: '', // Explicitly empty
        city: 'Mountain View',
        state: 'CA',
        zipCode: '94043',
        region: 'US',
    },
    nonExistentSubpremise: {
        streetAddress1: '2930 Pearl St.',
        streetAddress2: 'Suite 100',
        city: 'Boulder',
        state: 'CO',
        zipCode: '', // Explicitly empty
        region: 'US',
    },
    missingSubpremise: {
        streetAddress1: '500 West 2nd Street',
        streetAddress2: null, // Can use null or undefined too
        city: 'Austin',
        state: 'TX',
        zipCode: '78701',
        region: 'US',
    },
    misspelledLocality: {
        streetAddress1: '1600 Amphitheatre Pkwy',
        streetAddress2: '',
        city: 'Montan View',
        state: 'CA',
        zipCode: '94043',
        region: 'US',
    },
    missingLocality: {
        streetAddress1: 'Brandschenkestrasse 110 8002',
        streetAddress2: '',
        city: '',
        state: '',
        zipCode: '',
        region: '',
    },
    usPoBox: {
        streetAddress1: 'PO Box 1108',
        streetAddress2: '',
        city: 'Sterling',
        state: 'VA',
        zipCode: '20166-1108',
        region: 'US',
    },
};

// Helper function to populate form fields with example address data
function populateAddressFields(exampleAddress) {
    if (!exampleAddress) {
        console.warn('No example address data provided.');
        return;
    }

    // Get values from example, providing empty string as default
    streetAddress1Input!.value = exampleAddress.streetAddress1 || '';
    streetAddress2Input!.value = exampleAddress.streetAddress2 || '';
    cityInput!.value = exampleAddress.city || '';
    stateInput!.value = exampleAddress.state || '';
    zipCodeInput!.value = exampleAddress.zipCode || '';
    regionSelect!.value = exampleAddress.region || '';

    // Clear previous results and errors
    resultDisplay!.textContent = 'Result will appear here...';

    console.log('Populated fields with example: ', exampleAddress);
}

init();

JavaScript

// DOM Refs
const addressForm = document.getElementById('address-form');
const validateButton = document.getElementById('validate-button');
const clearFormButton = document.getElementById('clear-form-button');
const resultDisplay = document.getElementById('result-display');
const loadingText = document.getElementById('loading-text');
// Input field refs
const streetAddress1Input = document.getElementById('street-address-1');
const streetAddress2Input = document.getElementById('street-address-2');
const cityInput = document.getElementById('city');
const stateInput = document.getElementById('state');
const zipCodeInput = document.getElementById('zip-code');
const regionSelect = document.getElementById('region-select');
const exampleSelect = document.getElementById('example-select');
// Core Initialization
async function init() {
    // Load the Address Validation library.
    await google.maps.importLibrary('addressValidation');
    // Set event listeners
    addressForm.addEventListener('submit', handleValidationSubmit);
    exampleSelect.addEventListener('change', handleExampleSelectChange);
    clearFormButton.addEventListener('click', handleClearForm);
}
// Validation Handler
async function handleValidationSubmit(event) {
    event.preventDefault(); // Prevent default form submission
    resultDisplay.textContent = 'Validating...'; // Clear previous results
    // Validate the address
    try {
        //prettier-ignore
        //@ts-ignore
        const result = await google.maps.addressValidation.AddressValidation.fetchAddressValidation({
            address: {
                regionCode: regionSelect.value.trim(),
                languageCode: 'en',
                addressLines: [
                    streetAddress1Input.value.trim(),
                    streetAddress2Input.value.trim(),
                ].filter((line) => line), // Filter out empty lines
                locality: cityInput.value.trim(),
                administrativeArea: stateInput.value.trim(),
                postalCode: zipCodeInput.value.trim(),
            },
        });
        resultDisplay.textContent =
            'Verdict summary\n================\n' +
                `Formatted address: ${result.address.formattedAddress}\n` +
                `Entered: ${result.verdict.inputGranularity}\n` +
                `Validated: ${result.verdict.validationGranularity}\n` +
                `Geocoded: ${result.verdict.geocodeGranularity}\n` +
                `Possible next action: ${result.verdict.possibleNextAction}\n\n` +
                `${getVerdictMessage(result.verdict, 'addressComplete')}\n` +
                `${getVerdictMessage(result.verdict, 'hasUnconfirmedComponents')}\n` +
                `${getVerdictMessage(result.verdict, 'hasInferredComponents')}\n` +
                `${getVerdictMessage(result.verdict, 'hasReplacedComponents')}\n\n` +
                `Raw JSON response\n=================\n` +
                JSON.stringify(result, null, '  ');
    }
    catch (error) {
        console.error('Validation failed:', error);
        if (error instanceof Error) {
            resultDisplay.textContent = `Error: ${error.message}`;
        }
    }
}
// Verdict messages
const verdictMessages = {
    addressComplete: {
        trueMessage: '- The API found no unresolved, unexpected, or missing address elements.',
        falseMessage: '- At least one address element is unresolved, unexpected, or missing.',
    },
    hasUnconfirmedComponents: {
        trueMessage: "- The API can't confirm at least one address component.",
        falseMessage: '- The API confirmed all address components.',
    },
    hasInferredComponents: {
        trueMessage: '- The API inferred (added) at least one address component.',
        falseMessage: '- The API did not infer (add) any address components.',
    },
    hasReplacedComponents: {
        trueMessage: '- The API replaced at least one address component.',
        falseMessage: '- The API did not replace any address components.',
    },
};
// Helper function to get the verdict message for a given verdict key
function getVerdictMessage(verdict, key) {
    if (!verdict || !verdictMessages[key])
        return 'Unknown';
    return verdict[key]
        ? verdictMessages[key].trueMessage
        : verdictMessages[key].falseMessage;
}
// Handler for Dropdown Change
function handleExampleSelectChange(event) {
    const selectedValue = event.target.value;
    if (selectedValue && examples[selectedValue]) {
        populateAddressFields(examples[selectedValue]);
    }
    else if (!selectedValue) {
        populateAddressFields(null); // Pass null to clear fields
    }
}
// Clear Form Handler
function handleClearForm() {
    streetAddress1Input.value = '';
    streetAddress2Input.value = '';
    cityInput.value = '';
    stateInput.value = '';
    zipCodeInput.value = '';
    regionSelect.value = '';
    exampleSelect.value = '';
    resultDisplay.textContent = 'Result will appear here...';
    console.log('Cleared form');
}
// Example Address Data
const examples = {
    google: {
        streetAddress1: '1600 Amphitheatre Parkway',
        streetAddress2: '', // Explicitly empty
        city: 'Mountain View',
        state: 'CA',
        zipCode: '94043',
        region: 'US',
    },
    nonExistentSubpremise: {
        streetAddress1: '2930 Pearl St.',
        streetAddress2: 'Suite 100',
        city: 'Boulder',
        state: 'CO',
        zipCode: '', // Explicitly empty
        region: 'US',
    },
    missingSubpremise: {
        streetAddress1: '500 West 2nd Street',
        streetAddress2: null, // Can use null or undefined too
        city: 'Austin',
        state: 'TX',
        zipCode: '78701',
        region: 'US',
    },
    misspelledLocality: {
        streetAddress1: '1600 Amphitheatre Pkwy',
        streetAddress2: '',
        city: 'Montan View',
        state: 'CA',
        zipCode: '94043',
        region: 'US',
    },
    missingLocality: {
        streetAddress1: 'Brandschenkestrasse 110 8002',
        streetAddress2: '',
        city: '',
        state: '',
        zipCode: '',
        region: '',
    },
    usPoBox: {
        streetAddress1: 'PO Box 1108',
        streetAddress2: '',
        city: 'Sterling',
        state: 'VA',
        zipCode: '20166-1108',
        region: 'US',
    },
};
// Helper function to populate form fields with example address data
function populateAddressFields(exampleAddress) {
    if (!exampleAddress) {
        console.warn('No example address data provided.');
        return;
    }
    // Get values from example, providing empty string as default
    streetAddress1Input.value = exampleAddress.streetAddress1 || '';
    streetAddress2Input.value = exampleAddress.streetAddress2 || '';
    cityInput.value = exampleAddress.city || '';
    stateInput.value = exampleAddress.state || '';
    zipCodeInput.value = exampleAddress.zipCode || '';
    regionSelect.value = exampleAddress.region || '';
    // Clear previous results and errors
    resultDisplay.textContent = 'Result will appear here...';
    console.log('Populated fields with example: ', exampleAddress);
}
init();

CSS

body,
html {
    height: 100%;
    margin: 0;
    padding: 0;
    overflow: hidden;
    font-family: 'Google Sans', sans-serif;
    font-size: 20px;
    color: #333;
}

#sidebar {
    width: 800px;
    max-width: calc(100% - 2rem);
    background-color: #fff;
    border-color: #9ca3af;
    border-style: solid;
    border-radius: 0.5rem;
    box-shadow:
        0 4px 6px -1px rgba(0, 0, 0, 0.1),
        0 2px 4px -1px rgba(0, 0, 0, 0.06);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    max-height: calc(100% - 2rem);
}

.sidebar-header {
    padding: 0.75rem;
    border-bottom: 1px solid #e5e7eb;
    flex-shrink: 0;
}

.sidebar-header h2 {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 600;
    color: #1f2937;
}

.sidebar-content {
    padding: 0.75rem;
    overflow-y: auto;
    flex-grow: 1;
}

.sidebar-content::-webkit-scrollbar {
    width: 6px;
}

.sidebar-content::-webkit-scrollbar-thumb {
    background-color: rgba(0, 0, 0, 0.2);
    border-radius: 3px;
}

#address-form > div {
    margin-bottom: 0.75rem;
}

#address-form > button {
    margin-top: 1rem;
}

label {
    display: block;
    font-size: 0.75rem;
    font-weight: 500;
    color: #4b5563;
    margin-bottom: 0.25rem;
}

input[type='text'] {
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    border: 1px solid #d1d5db;
    border-radius: 0.375rem;
    box-sizing: border-box;
    transition:
        border-color 0.15s ease-in-out,
        box-shadow 0.15s ease-in-out;
}

input[type='text']:focus {
    outline: 0;
    border-color: #2563eb;
    box-shadow: 0 0 0 1px #2563eb;
}

.form-grid-triple {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
}

@media (max-width: 400px) {
    .form-grid-triple {
        grid-template-columns: 1fr;
    }
}

button {
    display: inline-block;
    margin-right: 0.5rem;
    width: auto;
    padding: 0.6rem 0.75rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: #fff;
    background-color: #2563eb;
    border: none;
    border-radius: 0.375rem;
    cursor: pointer;
    transition: background-color 0.15s ease-in-out;
    text-align: center;
}

button:hover {
    background-color: #1d4ed8;
}

#loading-indicator {
    margin-top: 0.5rem;
    font-size: 0.75rem;
    color: #2563eb;
    font-style: italic;
    display: none;
    align-items: center;
    gap: 0.5rem;
}

.spinner {
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spin 1s linear infinite;
    display: inline-block;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

#error-message {
    margin-top: 0.5rem;
    font-size: 0.75rem;
    color: #dc2626;
    font-weight: 500;
    display: none;
}

#result-container {
    margin-top: 1rem;
    border-top: 1px solid #e5e7eb;
    padding-top: 0.75rem;
}

#result-display {
    font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
    font-size: 0.75rem;
    background-color: #f3f4f6;
    padding: 0.5rem;
    border-radius: 0.25rem;
    overflow-x: auto;
    white-space: pre;
    height: 12rem;
    border: 1px solid #e5e7eb;
}

@media (max-width: 767px) {
    #sidebar {
        width: auto;
        max-width: 100%;
        margin: 0;
        max-height: 70vh;
        border-radius: 0;
        border-top-left-radius: 0.5rem;
        border-top-right-radius: 0.5rem;
        border-top: 1px solid #d1d5db;
        box-shadow:
            0 -4px 6px -1px rgba(0, 0, 0, 0.1),
            0 -2px 4px -1px rgba(0, 0, 0, 0.06);
    }
}

.form-select {
    display: block;
    width: 100%;
    padding: 0.5rem 2.5rem 0.5rem 0.75rem;
    font-size: 0.875rem;
    font-weight: 400;
    line-height: 1.5;
    color: #333;
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    background-size: 16px 12px;
    border: 1px solid #d1d5db;
    border-radius: 0.375rem;
    appearance: none;
    transition:
        border-color 0.15s ease-in-out,
        box-shadow 0.15s ease-in-out;
    cursor: pointer;
}

.form-select:focus {
    border-color: #2563eb;
    outline: 0;
    box-shadow: 0 0 0 1px #2563eb;
}

.form-select option[disabled] {
    color: #9ca3af;
}

HTML

<html>
    <head>
        <title>Address Validation</title>

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
    </head>
    <body>
        <!-- Address Validation Form Container -->
        <div id="sidebar">
            <!-- Header -->
            <div class="sidebar-header">
                <h2>Address Validation</h2>
            </div>
            <!-- Content: Address Form -->
            <form id="address-form" class="sidebar-content" autocomplete="off">
                <!-- Example Dropdown Section -->
                <div
                    id="example-dropdown-container"
                    style="
                        margin-bottom: 1rem;
                        padding-bottom: 0.75rem;
                        border-bottom: 1px solid #e5e7eb;
                    ">
                    <label for="example-select" style="margin-bottom: 0.5rem"
                        >Load Example Address:</label
                    >
                    <select
                        id="example-select"
                        name="exampleSelect"
                        class="form-select">
                        <option value="" selected disabled>
                            -- Select an Example --
                        </option>
                        <option value="google">Valid Address</option>
                        <option value="nonExistentSubpremise">
                            Non-existent Subpremise
                        </option>
                        <option value="missingSubpremise">
                            Missing Subpremise
                        </option>
                        <option value="misspelledLocality">
                            Misspelled Locality
                        </option>
                        <option value="missingLocality">
                            Missing Locality
                        </option>
                        <option value="usPoBox">US PO Box</option>
                    </select>
                </div>
                <div>
                    <label for="street-address-1">Street Address 1</label>
                    <input
                        id="street-address-1"
                        name="streetAddress1"
                        type="text"
                        placeholder="e.g., 1600 Amphitheatre Parkway" />
                </div>
                <div>
                    <label for="street-address-2"
                        >Street Address 2 (Optional)</label
                    >
                    <input
                        id="street-address-2"
                        name="streetAddress2"
                        type="text"
                        placeholder="e.g., Suite 100" />
                </div>
                <!-- Use a div with grid class for City/State/ZIP layout -->
                <div class="form-grid-triple">
                    <div>
                        <label for="city">City</label>
                        <input
                            id="city"
                            name="city"
                            type="text"
                            placeholder="e.g., Mountain View" />
                    </div>
                    <div>
                        <label for="state">State or territory</label>
                        <input
                            id="state"
                            name="state"
                            type="text"
                            placeholder="e.g., CA" />
                    </div>
                    <div>
                        <label for="zip-code">ZIP Code</label>
                        <input
                            id="zip-code"
                            name="zipCode"
                            type="text"
                            placeholder="e.g., 94043" />
                    </div>
                </div>
                <div id="region-select-container">
                    <div>
                        <label for="region-select">Region</label>
                        <select
                            id="region-select"
                            name="regionSelect"
                            class="form-select">
                            <option value="AR">Argentina</option>
                            <option value="AU">Australia</option>
                            <option value="AT">Austria</option>
                            <option value="BE">Belgium</option>
                            <option value="BR">Brazil</option>
                            <option value="BG">Bulgaria</option>
                            <option value="CA">Canada</option>
                            <option value="CL">Chile</option>
                            <option value="CO">Colombia</option>
                            <option value="HR">Croatia</option>
                            <option value="CZ">Czechia</option>
                            <option value="DK">Denmark</option>
                            <option value="EE">Estonia</option>
                            <option value="FI">Finland</option>
                            <option value="FR">France</option>
                            <option value="DE">Germany</option>
                            <option value="HU">Hungary</option>
                            <option value="IN">India</option>
                            <option value="IE">Ireland</option>
                            <option value="IT">Italy</option>
                            <option value="JP">Japan</option>
                            <option value="LV">Latvia</option>
                            <option value="LT">Lithuania</option>
                            <option value="LU">Luxembourg</option>
                            <option value="MY">Malaysia</option>
                            <option value="MX">Mexico</option>
                            <option value="NL">Netherlands</option>
                            <option value="NO">Norway</option>
                            <option value="NZ">New Zealand</option>
                            <option value="PL">Poland</option>
                            <option value="PT">Portugal</option>
                            <option value="PR">Puerto Rico</option>
                            <option value="SG">Singapore</option>
                            <option value="SK">Slovakia</option>
                            <option value="SI">Slovenia</option>
                            <option value="ES">Spain</option>
                            <option value="SE">Sweden</option>
                            <option value="CH">Switzerland</option>
                            <option value="GB">United Kingdom</option>
                            <option value="US" selected>United States</option>
                            <option value="">Unknown</option>
                        </select>
                    </div>
                </div>

                <button id="validate-button" type="submit">
                    Validate Address
                </button>

                <button
                    id="clear-form-button"
                    type="button"
                    event="handleClearForm">
                    Clear Form
                </button>

                <!-- Result Display Area -->
                <div id="result-container">
                    <label for="result-display"
                        >Validation Result (formatted address and JSON)</label
                    >
                    <pre id="result-display">Result will appear here...</pre>
                </div>
            </form>
        </div>
        <!-- prettier-ignore -->
        <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
      ({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "beta"});</script>
    </body>
</html>

Testar amostra