Skip to content

Address Element

The Address Element provides a complete address collection form with built-in autocomplete powered by Google Maps. Use it to collect shipping or billing addresses in your checkout flow.

Why Use Address Element?

FeatureBenefit
Google Maps AutocompleteCustomers find addresses faster with suggestions
International SupportHandles addresses from all countries with proper formatting
ValidationBuilt-in validation ensures complete, valid addresses
No Backend RequiredWorks immediately without a clientSecret

Basic Usage

vue
<script setup>
import {
  StripeProvider,
  StripeElements,
  StripeAddressElement
} from '@vue-stripe/vue-stripe'

const publishableKey = import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY

const addressOptions = {
  mode: 'shipping',
  autocomplete: { mode: 'automatic' }
}

const onChange = (event) => {
  if (event.complete) {
    console.log('Address complete:', event.value)
  }
}
</script>

<template>
  <VueStripeProvider :publishable-key="publishableKey">
    <VueStripeElements>
      <VueStripeAddressElement
        :options="addressOptions"
        @change="onChange"
      />
      <button>Continue</button>
    </VueStripeElements>
  </VueStripeProvider>
</template>

No clientSecret Required

Unlike Payment Element, Address Element works without a clientSecret. It only needs to be wrapped in VueStripeProvider and VueStripeElements to function.

Shipping vs Billing Mode

The mode option changes the form's behavior and labels:

vue
<script setup>
import { ref, computed } from 'vue'

const mode = ref('shipping')

const options = computed(() => ({
  mode: mode.value
}))
</script>

<template>
  <div class="mode-selector">
    <button @click="mode = 'shipping'">Shipping</button>
    <button @click="mode = 'billing'">Billing</button>
  </div>
  <!-- Key forces re-render when mode changes -->
  <VueStripeAddressElement :key="mode" :options="options" />
</template>
ModeUse Case
shippingPhysical delivery addresses
billingPayment verification addresses

Pre-filling Addresses

For returning customers, pre-fill their saved address:

vue
<script setup>
const options = {
  mode: 'shipping',
  defaultValues: {
    name: 'John Doe',
    phone: '+1 555-123-4567',
    address: {
      line1: '123 Main Street',
      line2: 'Apt 4B',
      city: 'San Francisco',
      state: 'CA',
      postal_code: '94102',
      country: 'US'
    }
  }
}
</script>

<template>
  <VueStripeAddressElement :options="options" />
</template>

Adding Phone Number

vue
<script setup>
const options = {
  mode: 'shipping',
  fields: {
    phone: 'always'  // 'always' | 'never' | 'auto'
  },
  validation: {
    phone: {
      required: 'always'  // Make phone required
    }
  }
}
</script>

<template>
  <VueStripeAddressElement :options="options" />
</template>

Limiting Countries

Restrict addresses to specific countries:

vue
<script setup>
const options = {
  mode: 'shipping',
  allowedCountries: ['US', 'CA', 'GB', 'AU']
}
</script>

<template>
  <VueStripeAddressElement :options="options" />
</template>

Blocking P.O. Boxes

For physical deliveries that require a street address:

vue
<script setup>
const options = {
  mode: 'shipping',
  blockPoBox: true
}
</script>

<template>
  <VueStripeAddressElement :options="options" />
</template>

Getting Address Data

Via Events

vue
<script setup>
import { ref } from 'vue'

const address = ref(null)
const isComplete = ref(false)

const handleChange = (event) => {
  isComplete.value = event.complete
  if (event.complete) {
    address.value = event.value
  }
}
</script>

<template>
  <VueStripeAddressElement @change="handleChange" />

  <div v-if="address">
    <p>{{ address.name }}</p>
    <p>{{ address.address.line1 }}</p>
    <p>{{ address.address.city }}, {{ address.address.state }}</p>
  </div>
</template>

Via Template Ref (Programmatic)

vue
<script setup>
import { ref } from 'vue'

const addressRef = ref()

const handleSubmit = async () => {
  const result = await addressRef.value?.getValue()

  if (result.complete) {
    console.log('Valid address:', result.value)
    // Proceed with checkout
  } else {
    alert('Please complete the address form')
  }
}
</script>

<template>
  <VueStripeAddressElement ref="addressRef" />
  <button @click="handleSubmit">Continue</button>
</template>

Integration with Payment Element

A common pattern is collecting address before payment:

vue
<script setup>
import { ref } from 'vue'
import {
  StripeProvider,
  StripeElements,
  StripeAddressElement,
  StripePaymentElement,
  useStripe,
  useStripeElements
} from '@vue-stripe/vue-stripe'

const publishableKey = import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY
const clientSecret = 'pi_xxx_secret_xxx' // From your backend

const addressRef = ref()
const step = ref('address')

const handleContinue = async () => {
  const result = await addressRef.value?.getValue()
  if (result?.complete) {
    step.value = 'payment'
  }
}
</script>

<template>
  <VueStripeProvider :publishable-key="publishableKey">
    <VueStripeElements :client-secret="clientSecret">
      <!-- Step 1: Address -->
      <div v-if="step === 'address'">
        <h3>Shipping Address</h3>
        <VueStripeAddressElement
          ref="addressRef"
          :options="{ mode: 'shipping' }"
        />
        <button @click="handleContinue">Continue to Payment</button>
      </div>

      <!-- Step 2: Payment -->
      <div v-if="step === 'payment'">
        <h3>Payment</h3>
        <VueStripePaymentElement />
        <button @click="step = 'address'">Back</button>
        <button>Pay Now</button>
      </div>
    </VueStripeElements>
  </VueStripeProvider>
</template>

Use Cases

  1. Checkout shipping — Collect where to ship physical goods
  2. Billing address — Collect for payment verification
  3. Customer profile — Store addresses for future use
  4. Multi-step checkout — Collect address before payment

Next Steps

Released under the MIT License.