Link Search Menu Expand Document

Handling customer data errors

When you call CF.customer.save, there are a number of things that can go wrong and it’s important to properly handle them to avoid a bad user experience.

How to access error data

CF.customer.save()
  .then(function(errorObj) {
    if (errorObj) {
      /* 
        errorObj is an object containing data column key to string array pairs. 
        Here's an example of what it might look like:

        {
          "phone": ["is invalid"],
          "email": ["has already been taken"],
        }
      */
    } else {
      // You're all set! Any unsaved changes that have been made 
      // to the customer's data have now been saved.
    }
  })
  .catch(function(err) {
    // Something wrong happened :(

    console.error("Could not save customer", err);
  });

errorObj can be a mixture of errors from Shopify and our servers complaining about incorrectly formatted data. Here’s a breakdown of its anatomy:

{
  "<data column key>": ["error one", "error two", "etc."],
  "<data column key 2>": ["error one", "error two", "etc."]
}

Possible errors for common fields

Data column key Possible errors
phone has already been taken, is invalid
email has already been taken, is invalid, must be verified
default_address.country is invalid
default_address.province is not valid
addresses.country is not a valid country
addresses.province is not valid
password is too short (minimum is 5 characters)
password_confirmation must match the provided password.

Note

Errors shown as addresses.country or addresses.province can result from fields that use default_address.country or default_address.province.

Render the errors in a form

If you’re working with a custom form, you’ll need to render the errors yourself. We’ve made this simple to do, using a library called Rivets:

<div data-cf-view>
  <ul class="errors" rv-if="has_error">
    <h5>Please fix errors:</h5>

    <li rv-each-error="errors.email">
      <span rv-if="error | eq 'verify'">
        Email must be verified.
      </span>
      
      <span rv-if="error | eq 'taken'">
        Email has already been taken.
      </span>
      
      <span rv-if="error | eq 'invalid'">
        Email is invalid.
      </span>
    </li>

    <li rv-each-error="errors.phone">
      <span rv-if="error | eq 'taken'">
        Phone number has already been taken.
      </span>
      
      <span rv-if="error | eq 'invalid'">
        Phone number is invalid.
      </span>
    </li>

    <li rv-each-error="errors.default_address.country">
      <span rv-if="error | eq 'invalid'">
        Country is invalid.
      </span>
    </li>

    <li rv-each-error="errors.default_address.province">
      <span rv-if="error | eq 'invalid'">
        Province is invalid.
      </span>
    </li>

    <li rv-each-error="errors.addresses.country">
      <span rv-if="error | eq 'invalid'">
        Country is invalid.
      </span>
    </li>

    <li rv-each-error="errors.addresses.province">
      <span rv-if="error | eq 'invalid'">
        Province is invalid.
      </span>
    </li>

    <li rv-each-error="errors.password">
      <span rv-if="error | eq 'too_short'">
        Password is too short (minimum is 5 characters)
      </span>
    </li>

    <li rv-each-error="errors.password_confirmation">
      <span rv-if="error | eq 'must_match_password'">
        Password confirmation must match the provided password.
      </span>
    </li>
  </ul>
</div>

There are two rivets state variables in play here: has_error, and errors.

has_error is simply a boolean flag that is true whenever our servers reject a submission from a rivets form.

The errors object is only present if a rivets form has been submitted and our servers have returned errors. Otherwise, it is null. When it is defined, it looks something like this:

{
  email: ['invalid', 'taken'],
  phone: ['invalid'],
}

The above markup demonstrates how to properly access and display those errors. If you already have an element with a data-cf-view attribute, disregard the parent <div data-cf-view> element in the example.

Note: some errors may not be applicable, so for example if you don’t have a phone field, you don’t need to output errors from errors.phone.


Have any questions or comments about this post? Let us know! Your feedback is greatly appreciated.

Customer Fields is a Shopify app made by Helium.

Copyright © Helium Development, LLC