Skip to content

Instantly share code, notes, and snippets.

@estrattonbailey
Created August 29, 2016 18:20
Show Gist options
  • Save estrattonbailey/bded6de049b8c10f1ba6850eb5b6d6bf to your computer and use it in GitHub Desktop.
Save estrattonbailey/bded6de049b8c10f1ba6850eb5b6d6bf to your computer and use it in GitHub Desktop.
Shopify Address Form
<div id="{{form_outer_id}}" class="address__form relative w1 {{form_classes}}" style="display: none;">
{% form 'customer_address', form_action %}
{% assign form_id = form.id %}
{% capture form_script %}{% if form_id == 'new' %}barrel.toggleNewForm(event){% else %}barrel.toggleForm(event, {{form_id}}){% endif %}{% endcapture %}
{% capture form_suffix %}{% if form_id and form_id != 'new' %}_{{form_id}}{% endif %}{% endcapture %}
{% capture form_city_id %}{% if form_id == 'new' %}AddressCityNew{% else %}AddressCity{% endif %}{% endcapture%}
{% capture form_country_id %}{% if form_id == 'new' %}AddressCountryNew{% else %}AddressCountry{% endif %}{% endcapture%}
{% capture form_province_container_id %}{% if form_id == 'new' %}AddressProvinceContainerNew{% else %}AddressProvinceContainer{% endif %}{% endcapture%}
{% capture form_province_id %}{% if form_id == 'new' %}AddressProvinceNew{% else %}AddressProvince{% endif %}{% endcapture%}
<h4>{{form_title}}</h4>
<div class="address__form__group flex flex-wrap flex-justify">
<p class="address__form__field">
<label for="AddressFirstNameNew{{form_suffix}}" class="block">First Name:</label>
<input id="AddressFirstNameNew{{form_suffix}}" class="block w1" type="text" name="address[first_name]" value="{{form.first_name}}" autocapitalize="words">
</p>
<p class="address__form__field">
<label for="AddressLastNameNew{{form_suffix}}" class="block">Last Name:</label>
<input id="AddressLastNameNew{{form_suffix}}" class="block w1" type="text" name="address[last_name]" value="{{form.last_name}}" autocapitalize="words">
</p>
</div>
<div class="address__form__group flex flex-wrap flex-justify">
<p class="address__form__field">
<label for="AddressCompanyNew{{form_suffix}}" class="block">Company:</label>
<input id="AddressCompanyNew{{form_suffix}}" class="block w1" type="text" name="address[company]" value="{{form.company}}" autocapitalize="words">
</p>
<p class="address__form__field">
<label for="AddressPhoneNew{{form_suffix}}" class="block">Phone:</label>
<input id="AddressPhoneNew{{form_suffix}}" class="block w1" type="tel" name="address[phone]" value="{{form.phone}}">
</p>
</div>
<div class="address__form__group flex flex-wrap flex-justify">
<p class="address__form__field">
<label for="AddressAddress1New{{form_suffix}}" class="block">Address1:</label>
<input id="AddressAddress1New{{form_suffix}}" class="block w1" type="text" name="address[address1]" value="{{form.address1}}" autocapitalize="words">
</p>
<p class="address__form__field">
<label for="AddressAddress2New{{form_suffix}}" class="block">Address2:</label>
<input id="AddressAddress2New{{form_suffix}}" class="block w1" type="text" name="address[address2]" value="{{form.address2}}" autocapitalize="words">
</p>
</div>
<div class="address__form__group flex flex-wrap flex-justify">
<p class="address__form__field">
<label for="{{form_city_id}}{{form_suffix}}" class="block">City:</label>
<input id="{{form_city_id}}{{form_suffix}}" class="block w1" type="text" name="address[city]" value="{{form.city}}" autocapitalize="words">
</p>
<p class="address__form__field">
<label for="{{form_country_id}}{{form_suffix}}" class="block">Country:</label>
<span class="select-wrapper w1">
<select id="{{form_country_id}}{{form_suffix}}" class="block w1" name="address[country]" data-default="{{ form.country }}">{{ country_option_tags }}</select>
</span>
</p>
</div>
<div class="address__form__group flex flex-wrap flex-justify">
<p class="address__form__field">
<span id="{{form_province_container_id}}{{form_suffix}}" style="display:none">
<label for="{{form_province_id}}{{form_suffix}}" class="block">Province:</label>
<span class="select-wrapper w1">
<select id="{{form_province_id}}{{form_suffix}}" class="w1" name="address[province]" data-default="{{ form.province }}"></select>
</span>
</span>
</p>
<p class="address__form__field">
<label for="AddressZipNew{{form_suffix}}" class="block">Zip:</label>
<input id="AddressZipNew{{form_suffix}}" class="block w1" type="text" name="address[zip]" value="{{form.zip}}" autocapitalize="words">
</p>
</div>
<p>
<label for="address_default_address_new{{form_suffix}}" class="checkbox mr05">
{{ form.set_as_default_checkbox }}
Set as default address
</label>
</p>
<p class="pt1">
<button type="submit" class="button">{{form_cta}}</button>
<a href="#0" class="ml1 underline" onclick="{{form_script}}">Cancel</a>
</p>
{% endform %}
</div>
{% assign form_id = false %}
{% assign form_classes = '' %}
<script>
(function(){
var form = document.getElementById({{form_outer_id | json}})
var countrySelector = document.getElementById({{form_country_id | json}}+{{form_suffix | json}})
var provinceContainer = document.getElementById({{form_province_container_id | json}}+{{form_suffix | json}})
var provinceSelector = document.getElementById({{form_province_id | json}}+{{form_suffix | json}})
var countryDefault = countrySelector.getAttribute('data-default') ? countrySelector.getAttribute('data-default') : countrySelector.options[0].value
var provinceDefault = provinceSelector.getAttribute('data-default')
/**
* Select an option within a <select>
* based on a given value
*
* @param {string} value Value to search for
* @param {element} select <select> element
* @return {element} The first matching select option
*/
function selectOption(value, select){
return Array.prototype.slice.call(select.options).filter(function(option, i){
if (option.value === value){
select.selectedIndex = i
return true
}
return false
})[0]
}
/**
* Generate province options and show select element
*
* @param {array} options Array of arrays from selected country
*/
function showProvinces(options){
var previousValue = provinceSelector.options[0] ? provinceSelector.options[0].value : false
var isNewValue = !previousValue || options[0][0] !== previousValue ? true : false
if (isNewValue){
// Emptry provinces select
provinceSelector.innerHTML = ''
// Generate new options from values
for (var i = 0; i < options.length; i++){
var option = document.createElement('option')
option.value = options[i][0]
option.innerHTML = options[i][1]
provinceSelector.appendChild(option)
}
}
// Select the default province
if (provinceDefault.length > 0) selectOption(provinceDefault, provinceSelector)
// Show provinces
provinceContainer.style.display = 'block'
}
/**
* Hide provinces container
*/
function hideProvinces(){
provinceContainer.style.display = 'none'
}
/**
* If we have an active default country,
* select it and select it's default province
*
* (this is for the edit form)
*/
function selectDefaults(){
if (countryDefault.length < 1) return
var selectedCountry = selectOption(countryDefault, countrySelector)
var options = JSON.parse(selectedCountry.getAttribute('data-provinces'))
showProvinces(options)
}
/**
* Setup onchange listener for countries
*/
countrySelector.onchange = function(e){
var selectedOption = countrySelector.options[countrySelector.selectedIndex]
var options = JSON.parse(selectedOption.getAttribute('data-provinces')) || []
options.length > 0 ? showProvinces(options) : hideProvinces()
}
selectDefaults()
})()
</script>
@estrattonbailey
Copy link
Author

Use like this for the "Add Address" form:

{% assign form_outer_id = 'newAddress' %}
{% assign form_action = customer.new_address %}
{% assign form_title = 'Add New Address' %}
{% assign form_cta = 'Add Address' %}
{% assign form_classes = 'mb2 pb1' %}

{% include 'account-address-form' %}

Or like this for the individual address forms:

{% for address in customer.addresses %}
    {% assign form_outer_id = 'editAddress' | append: '_' | append: address.id %}
    {% assign form_action = address %}
    {% assign form_title = 'Edit Address' %}
    {% assign form_cta = 'Update Address' %}
    {% assign form_classes = 'mb2 active-top' %}

    {% include 'account-address-form' %}
{% endfor %}

@estrattonbailey
Copy link
Author

Utility functions (in addresses.liquid):

<script>
  window.addresses = {
    toggleForm: function(e, id) {
      e.preventDefault()
      var el = document.getElementById('editAddress_'+id)
      el.style.display = el.style.display == 'none' ? '' : 'none'
    },
    toggleNewForm: function(e) {
      e.preventDefault()
      var el = document.getElementById('newAddress')
      el.style.display = el.style.display == 'none' ? '' : 'none'
    },
    removeAddress: function removeAddress(e, id){
      e.preventDefault()

      if (!confirm("Are you sure you wish to delete this address?")) return

      var form = document.createElement("form")
      var input = document.createElement("input");

      form.setAttribute('method', 'post')
      form.setAttribute("action", '/account/addresses/'+id)

      input.setAttribute("type", "hidden")
      input.setAttribute("name", '_method')
      input.setAttribute("value", 'delete')

      form.appendChild(input)

      document.body.appendChild(form)
      form.submit()
      document.body.removeChild(form)
    }
  } 
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment