Link

Overview

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
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 on the document yourself. Here’s a snippet that will render the errors as a list above your form’s fields:

var handleCustomerSaveErrors = function(errorObj) {
  // If we don't have any errors, we don't have to do anything! :)
  if (!errorObj) return;

  // Create a <ul> element
  var $errorList = document.createElement('ul');

  // Set an ID that we can use to find this error list and delete it later on
  $errorList.id = 'errors';

  var $form = document.querySelector('form#create_customer');

  for (var columnKey in errorObj) {
    var errors = errorObj[columnKey];
    
    // Add <li> elements to our <ul> containing individual errors (cause there may be more than one!)
    errors.forEach(function(errorText) {
      var $item = document.createElement('li');
      let errorToDisplay = '';

      // Manually detect the key and error message to display a clear error message to the customer.
      switch (columnKey) {
        case 'email':
          switch (errorText) {
            case 'has already been taken':
              errorToDisplay = 'Email address is already in use.';
              break;
            case 'is invalid':
              errorToDisplay = 'Email address is invalid.';
              break;
          }
          break;
        case 'phone':
          switch (errorText) {
            case 'has already been taken':
              errorToDisplay = 'Phone number is already in use.';
              break;
            case 'is invalid':
              errorToDisplay = 'Phone number is invalid.';
              break;
          }
          break;
        case 'addresses.country':
          if (errorText == 'is not a valid country') {
            errorToDisplay = 'Specified country is invalid.';
          }
          break;
        case 'addresses.province':
          if (errorText == 'is not valid') {
            errorToDisplay = 'Specified province is invalid.';
          }
          break;
        case 'password':
          if (errorText == 'is too short (minimum is 5 characters)') {
            errorToDisplay = 'Password must be at least 5 characters long.';
          }
          break;
        case 'password_confirmation':
          if (errorText == 'must match the provided password.') {
            errorToDisplay = 'Password confirmation must match the provided password.';
          }
          break;
        default:
          errorToDisplay = 'Unknown error has occurred, please reach out to us at contact@email.com';
          break;
      }

      // Set the text of our <li> element
      $item.innerText = errorToDisplay;

      // Append the <li> to our <ul>
      $errorList.appendChild($item);
    });
  }
  
  // Finally, display our errors before the first child element
  $form.insertBefore($errorList, $form.firstElementChild);
}

// Do we already have an errors element? If so, remove it, because it may not be relevant anymore.
const $oldErrors = document.querySelector('ul#errors');
if ($oldErrors) $oldErrors.parentElement.removeChild($oldErrors);

CF.customer.save()
  .then(function(errorObj) {
    handleCustomerSaveErrors(errorObj);
  })
  .catch(function(err) {
    // Failed to send request, or parse the server response (if any.)
    console.error(err);
  });