We use the address field on the user profile, and expose the CRUD services of the user through the services module.

The problem: address field fails validation when a country other than the default country is submitted. "An illegal choice in <em class="placeholder">State</em> element has been detected." is the error received. This is due to the form not updating its widget something along the lines of this issue http://drupal.org/node/1861608 however that is not working in this use case when using services.

Comments

roam2345’s picture

We have implemented this in the mean time to work around this issue.

/**
 * Implements hook_field_widget_form_alter().
 *
 * This is used to fix the form widget for submissions through services.
 */
function sac_services_field_widget_form_alter(&$element, &$form_state, $context) {
  // Ensure, we're attaching field into right entity type
  if ($context['instance']['entity_type'] == 'user' && $context['field']['field_name'] == 'field_profile_address_address' ) {
    if (isset($form_state['values']['field_profile_address_address'][LANGUAGE_NONE][0]['country'])) {
      //Set the address country default before re-generating the widget.
      $context['items'][$context['delta']]['country'] = $form_state['values']['field_profile_address_address'][LANGUAGE_NONE][0]['country'];

      // Prepare some data to be passed into addressfield_field_widget_form.
      $element_info = array(
        '#entity_type' => $element['#entity_type'],
        '#bundle' => $element['#bundle'],
        '#field_name' => $element['#field_name'],
        '#language' => $element['#language'],
        '#delta' => $element['#delta'],
      );

      // regenerate the widget.
      $format = addressfield_field_widget_form($context['form'], $form_state, $context['field'], $context['instance'], $context['langcode'], $context['items'], $context['delta'], $element_info);

      // Switch out the form elements with our newly generated ones.
      foreach ($element as $key => $value) {
        if (isset($format[$key])) {
          $element[$key] = $format[$key];
        }
      }
    }
  }
}
rszrama’s picture

Status: Active » Postponed (maintainer needs more info)

I'm not sure I follow. What is there here for the Address Field module to actually do?

fwiw, I disagree with the Services philosophy of performing field CRUD using the form system; if that's what this is about, then I'd probably advise you to find some alternate method of creating / updating entities. In http://drupal.org/project/commerce_services I've created my own resource plugins for Commerce entities that will do this via a straight JSON representation of the data itself instead of trying to POST executable form data.

aramboyajyan’s picture

Issue summary: View changes

For anyone who stumbles upon the same issue, I can confirm that the implementation in #1 works properly.

Here's some clarification to what issue is exactly:

- In our setup, Services are used to clone new users to another website, meaning CRUD is open for User entity.
- One of the user profile fields is using Addressfield.
- Addressfield changes country dropdown options dynamically (with an AJAX request), meaning the county dropdown is different for US and Canada.
- This causes validation issues whenever admins/users create new accounts with country other than the default one.
- This is because the services module on the receiving end has different fields for form validation, and that is where the process fails.

I am not sure where the fix should go in Addressfield module, but I hope the explanation above will help maintainers understand the issue.

Thanks!

eanushan’s picture

Can confirm. Running into the same issue. What #3 says is accurate. Default Drupal validation for select fields runs, and the county dropdown (Province/State) doesn't have the expected values for a new country.

For example, if you start out with the country being Canada, you'll have the provinces available in the county drop down (i.e Ontario, Alberta etc.)

Now if you update the user via the services module, and switch the country to United States, and then try to set the county to "Alabama", Drupal will fail the validation for the field since "Alabama" is not in the original province list of Ontario, Alberta etc.

This doesn't happen with the regular form because when you switch countries, an AJAX callback runs to fetch the new Province/State dropdown, which updates the valid select values for this drop down in the backend.

eanushan’s picture

Here is a more generic fix for all address fields, regardless of field name and entity type. It will require some code style cleanup. Place this in hook_field_widget_form_alter in any custom module.

Edit: This fix is no longer needed. The latest addressfield (7.x-1.0) fixes the issue. Including this fix will actually result in 500 errors now. Discussed and confirmed with @tyler.frankenstein.

  // This is used to fix the form widget for submissions through services for addressfield fields.
  // See: https://www.drupal.org/node/1933438
  if(module_exists('addressfield') && $context['field']['type'] == 'addressfield')
  {
    if(isset($form_state['values'][$context['field']['field_name']][LANGUAGE_NONE][0]['country']))
    {
      // Set the address country default before re-generating the widget.
      $context['items'][$context['delta']]['country'] = $form_state['values'][$context['field']['field_name']][LANGUAGE_NONE][0]['country'];
      
      // Prepare some data to be passed into addressfield_field_widget_form.
      $element_info = array(
          '#entity_type' => $element['#entity_type'],
          '#bundle' => $element['#bundle'],
          '#field_name' => $element['#field_name'],
          '#language' => $element['#language'],
          '#delta' => $element['#delta']
      );
      
      // Regenerate the widget.
      $format = addressfield_field_widget_form($context['form'], $form_state, $context['field'], $context['instance'], $context['langcode'], $context['items'], $context['delta'], $element_info);
      
      // Switch out the form elements with our newly generated ones.
      foreach ($element as $key => $value)
      {
        if (isset($format[$key]))
        {
          $element[$key] = $format[$key];
        }
      }
    }
  }
damien tournoud’s picture

Status: Postponed (maintainer needs more info) » Closed (won't fix)

There is nothing wrong with Entity Reference. The default resources shipped in the Services module are broken by design, because they try to use the UI forms to process API requests. Use Services Entity API instead of the default resources, or switch altogether to a better API framework like RestWS.

damien tournoud’s picture

Status: Closed (won't fix) » Closed (works as designed)
tyler.frankenstein’s picture

I've created a contrib module to help with an Address Field via Services: https://www.drupal.org/project/services_addressfield

aramboyajyan’s picture

Thanks for putting up the module and posting the link here!

On another note - seems something went wrong with comment timestamps - Damien's comments are dated to October 2014 even though they were posted today/yesterday.