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
oraddresses.province
can result from fields that usedefault_address.country
ordefault_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
.