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 {
  VueStripeProvider,
  VueStripeElements,
  VueStripeAddressElement
} 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 {
  VueStripeProvider,
  VueStripeElements,
  VueStripeAddressElement,
  VueStripePaymentElement
} 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.