I tried using it like this, but it did not work.

  $form['personalinfo']['address'] = array(
    '#type' => 'addressfield',
    '#title' => t('Address'),
    '#required' => TRUE,
    '#default_value' => array('country' => 'Denmark'),
    '#description' => "Please enter your address.",
    '#default_widget' => 'addressfield_standard',
    '#default_formatter' => 'addressfield_default',
  );

Could you supply some documentation on how to use it?

CommentFileSizeAuthor
#135 interdiff-970048-133-135.txt1.5 KBhargobind
#135 addressfield-form-element-970048-135.patch15.16 KBhargobind
#133 interdiff-970048-125-133.txt2.43 KBjoelstein
#133 addressfield-form-element-970048-133.patch14.65 KBjoelstein
#127 interdiff-970048-121-125.txt678 bytesAnas_maw
#125 addressfield_define_and_use-970048-125.patch15.03 KBAnas_maw
#121 addressfield_define_and_use-970048-121.patch14.36 KBAyesh
#120 addressfield_define_and_use-970048-120.patch14.35 KBAyesh
#119 define_and_use-addressfield-970048-119.patch14.01 KBAyesh
#114 addressfield-element_info-970048-114.patch14.37 KBhargobind
#113 addressfield-element_info-970048-113.patch13.25 KBsagannotcarl
#109 Clipboard01.png70.86 KBhargobind
#105 addressfield-element_info-970048-105-interdiff.patch901 byteshargobind
#105 addressfield-element_info-970048-105.patch13.26 KBhargobind
#104 define_and_use-970048-104-interdiff.patch901 byteshargobind
#104 define_and_use-970048-104.patch13.26 KBhargobind
#103 addressfield-element_info-970048-103-interdiff.patch2.04 KBAyesh
#103 addressfield-element_info-970048-103.patch13.33 KBAyesh
#102 addressfield-element_info-970048-102.patch12.59 KBstewart.adam
#82 addressfield-element_info-970048-82.patch11.58 KBJohnny vd Laar
#79 addressfield-element_info-970048-79.patch11.06 KBtien.xuan.vo
#71 addressfield-element_info-970048-71.patch10.57 KBstewart.adam
#71 commerce_addressbook-addressfield_element_info-970048-71.patch746 bytesstewart.adam
#71 commerce_customer-addressfield_element_info-970048-71.patch811 bytesstewart.adam
#64 addressfield-element_info-970048-64.patch10.23 KBstewart.adam
#49 addressfield-element_info-970048-49.patch2.58 KBstewart.adam
#43 addressfield-element_info-970048-43.patch2.57 KBstewart.adam
#31 addressfield-element_info-970048-31.patch2.34 KBgrantlucas
#25 addressfield-element_info-970048-25.patch2.33 KBgrantlucas
#21 addressfield-element_info-970048-21.patch2.16 KBgrantlucas
#16 addressfield-element_info-970048-16.patch2.06 KBgrantlucas
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rszrama’s picture

Title: Apply example on how to use address field with the form api » Define and use addressfield as a form element type
Component: Documentation » Code

Hmm, interesting thought... what you're attempting to do is use the Field as a form element. The two don't naturally go hand in hand, though. The Address Field module currently only does the part of defining a Field you can attach to entity bundles (like Commerce customer profile types) to collect data via those bundles' add / edit forms. I'll switch the title on this though to a request for a new form element type... I don't think it should be much more work to make this work in that way, and then we can simplify the Field itself to use the addressfield form element.

This won't be high priority, but it shouldn't be a ton of work.

Damien Tournoud’s picture

Priority: Normal » Major

I want this :)

wesnick’s picture

Seems like this has been mostly implemented (thanks @Damien!). I have been able to add the addressfield to a generic form using this code, but was not sure if this was the correct way to do it:

  $address = addressfield_default_values('US');
  $handlers = array(
    'address' => 'address',
  );
  $context = array(
    'mode' => 'form'
  );
  $form['myaddress'] = addressfield_generate($address, $handlers, $context);
  unset($form['myaddress']['country']);

I am not interested in the country part, but if I leave it in the form, it will fail validation.

bfroehle’s picture

Haven't thought about it much, but the first step would be to add an entry to hook_element_info():

+  $types['addressfield'] = array(
+    '#process' => array('addressfield_element_process'),
+    '#context' => array('mode' => 'form'),
+    '#handlers' => array('address' => 'address'),
+  );

and create an addressfield_element_process() function:

+function addressfield_element_process($element) {
+  $element['address'] = addressfield_generate($element['#default_value'], $element['#handlers'], $element['#context']);
+  $element['address']['element_key'] = array(
+    '#type' => 'value',
+    '#value' => 0,
+  );
+  return $element;
+}

Usage would then be something like:

  $form['address'] = array(
    '#type' => 'addressfield',
    '#title' => t('Address'),
    '#required' => TRUE,
    '#default_value' => addressfield_default_values('US'),
    '#description' => "Please enter your address.",
  );

There are still lots of kinks -- the description doesn't get used, for example -- but the form at least displays.

It'll probably be necessary to add a '#value_callback' to the element as well.

Darren Shelley’s picture

+1

This would be a great feature.

I'm looking to create a custom form which harnesses addressfield and postcode lookup software.

melissavdh’s picture

+1 I'm also looking for a way to do this. Using the snippets above I can get the addressfield widget appearing in any custom form but the form fields are not changing when a different country is selected. Also the "State" field is always appearing as just a textfield rather than a select list of State options.

Has anyone found a way around this? It seems to me that the form widget is not being rebuilt properly when the Country value changes.

pfrenssen’s picture

I can confirm that the form fields do not adapt themselves when chosing another country as reported in #6. Also when I change the country and then submit the form the form validation does not pass, but no error message is set.

jurgenhaas’s picture

Same here: changing the country doesn't change the fields and submitting the form just shows the form again without any error message.

In addition to that, I always get the following notice in watchdog when the form gets built:

Notice: Undefined index: element_key in addressfield_standard_country_validate() (Line 490 in sites/all/modules/addressfield/addressfield.module).
pichot’s picture

I'm also getting this error. Any ideas would be appreciated.

damien_vancouver’s picture

I sure would love this feature too. I rolled out Drupal commerce, and the clients rejoiced! My clients then wanted that awesome address selector on their signup form, which is hooked up to a custom submit handler and runs some API integration and so on... preventing me from using a node edit/create form.

I attempted the solution from #3 above (also concisely summarized at #1302712: What's the best way to include an addressfield widget into a form), but like the others on this thread I had problems. The form appears OK, but changing the country dropdown fires some ajax which doesn't do anything (ie., the form does not rewrite to match that country, which is the main feature my clients want to see).

I'm guessing that I'm just missing some more stuff in my form API code - maybe a submit handler for the ajax, something like that?

Looking through the drupal commerce customer module line 947, I see that commerce does it by implementing hook_field_widget_form(), and makes the form by using field_attach_form(), rather than as a Form API code snippet. I assume field_attach_Form is adding the missing magic, or it's just somewhere else in the code I"m not seeing with my novice eyes.

I think what we need to close this issue, and would be really useful for addressfield, is simple instructions on how to add an "addressfield" form in Form API code. The above from #3, but also the necessary AJAX stuff to make it update the country code and redraw the form properly. This may well entail doing it differently, ie. implementing hook_field_widget_form() and using field_attach_form(). I'm out of my depth though, and have gone back to just copying the layout of my client's home country (UK) in a dumb form API form of fields for now. This information is just what I sleuthed out in last night's attempt, and hopefully it's useful.

jurgenhaas’s picture

Category: feature » support

Same here. Still the warning described in #8 is still happening and also changing the country doesn't do anything, exactly like described in #10. Any help available and those two issues?

rszrama’s picture

Category: support » feature

Let's leave this a feature request - we need to actually add support for this in code for it to work using I think hook_element_info() or something.

damien_vancouver’s picture

Thanks for the clarification Ryan! I've shelved this into the "nice to have after launch" pile for my current project, but I know my clients do still want it, so I can spend some time later to figure it out more and do some of the grunt work (if no one else gets to it first).

ETA for that from me is probably 1-2 months. I'll post back here when I'm able to get back into it, or I'll help with testing etc. if someone else does it first.

sammys’s picture

Here's an addendum to #4 so the AJAX stuff works and it has more functionality. E.g. Can limit the countries shown in the list.

Change addressfield_element_process() to this:

+function addressfield_element_process($element, &$form_state, $form) {
+  // Inject context defaults
+  $element['#context'] += array(
+    'mode' => 'form',
+  );
+  $element_key = implode('|', $element['#array_parents']);
+
+  if (!empty($form_state['addressfield'][$element_key])) {
+    // Use the value from the form_state if available.
+    $address = $form_state['addressfield'][$element_key];
+  }
+  else {
+    $address = (array) $element['#default_value'];
+  }
+
+  $countries = country_get_list();
+  if (is_array($element['#context']['countries']) && count($element['#context']['countries'])) {
+    $countries = array_intersect_key($countries, drupal_map_assoc($element['#context']['countries']));
+  }
+  $element['#context']['countries'] = $countries;
+  $address += addressfield_default_values($element['#context']['countries']);
+
+  $element['address'] = addressfield_generate($address, $element['#handlers'], $element['#context']);
+  $element['address']['element_key'] = array(
+    '#type' => 'value',
+    '#value' => $element_key,
+  );
+
+  // Restrict the country options to only those desired
+  $element['address']['country']['#options'] = $element['#context']['countries'];
+ 
+  return $element;
+}

And the form field declaration needs to be something more like this:

$form['your_address'] = array(
    '#type' => 'addressfield',
    '#title' => t('Address'),
    '#context' => array('countries' => array('US')), // Countries to display in the select list
    '#default_value => array('country' => 'AU'), // Selects Australia by default
    '#description' => "Please enter your address.",
  );

You can leave out #context to get the full list of countries.

grantlucas’s picture

Is there a patch file available which combines #4 and #14? I'm looking to implement this. If there is no patch file as of yet, I will attempt to apply the changes and upload.

grantlucas’s picture

Status: Active » Needs review
FileSize
2.06 KB

I've taken the code contributed above with a few tweaks and put together a patch which now adds "#type" => "addressfield" support. I've tested it against the latest dev branch and it all seems to work alright. Would appreciate other testing as well.

Added hook_element info from #4 and the process function from #14.

Patch also works again Beta2 for those interested.

rszrama’s picture

Wow, thanks for making this into a patch. Another thought here is that if we have an addressfield element type, then the addressfield widget form itself could be updated to use the new element type instead of duplicating any code.

Barry_Fisher’s picture

All good on the patch front. I now have addressfield working in a custom form. Thanks @grantlucas for that.

One caveat- the function country_get_list() is provided by the core locale module and so places a dependency on addressfield to require locale.

I see there are a few options to solve this:

Option 1 : The the addressfield module (and patch above) could include the includes/locale.inc file. This would give a bit of overhead for just the one function required.

Option 2 : Copy the country_get_list() function from locale.inc and copy it to address field to save the overhead in loading the whole locale.inc into memory. This would ensure that any country list override would still get picked up by other modules if implemented via the drupal_alter('countries', $countries);

Option 3 : Go for a full locale module dependency in the addressfield.info file.

What's the consensus here?

Barry_Fisher’s picture

It would seem (for me at least) that rendering the form element in this way doesn't print out the #title defined as above. I only get the addressfield element- no title. Does anyone else have an issue with this? I've had a quick play to see how and where this could/should be rendered out (theme wrappers and the like) but haven't had much luck identifying where the problem is. Any pointers please?

grantlucas’s picture

I took a quick look around the addressfield module and came across where the actual form is put together in _addressfield_process_format_form() in addressfield.module. From what I can gather with what the original intentions may have been is that the address input can be contained in a large variety of formats and thus displaying the title is not always the best option.

What's happening at the moment is that the original "addressfield" element is replaced with all the new form inputs to create the addressfield. In doing this, the original title is also ignored. The way this module handles it when included with a profile for example is that the addressfield element is within a fieldset who's title would be "Mailing Address" for example. This visually contains all the fields which belong to the address.

As of right now, the best approach would be containing the adressfield in a fieldset manually.

A patch could be put together to render out the title as well, but here's one example where doing so would not be best. I want to collect a shipping or mailing address of a user as part of a larger form. Applicable to that address is the person's first name, last name, and company. As it stands right now, I can wrap those three fields AND the addressfield in one fieldset titled "Mailing Address" and all the important information is grouped visually together.

If something with title is done in the addressfield module itself, I can see a lot of situations where that functionality would have to be overridden anyways.

Does that make sense or help?

grantlucas’s picture

Ah good catch on the locale.inc. I looked where else it was used in the addressfield module and includes/locale.inc was being included before using the function. I've attached a new patch to replace the one in #16 with the added require_once of locale.inc to keep in line with the rest of the module.

Please revert the address field to the original and re-apply this patch to ensure that it works like fully intended.

Barry_Fisher’s picture

Point understood about the fieldset option. I can use that in my case just fine and have the legend indicate the title required. Thanks for the pointer.

grantlucas’s picture

Would be great to get a few more reviews on the patch to get it marked reviewed and tested. Wouldn't mind seeing this patch applied to an upcoming release. If it's an issue of the widget also using the new form element, I'm sure I can get that worked in. Do we want to move it over to use the new element?

nclavaud’s picture

Applied patch #21 on 7.x-1.x-dev.

However I'm facing a strange issue. My form has a required field of type "radios", and it seems like the addressfield Ajax breaks if no option is selected in the radio field (see code below).

Scenario 1 : answer the radio field (1 or 2), then select Canada in the addressfield.
Result : expected behavior (the address form updates correctly and now shows the "Province" field).

Scenario 2 : do not answer the radio field, then select Canada in the addressfield.
Result : the address form does not update.

Might be related to this other Form API issue?
#811542: Regression: Required radios throw illegal choice error when none selected

What's more, is there a way to require an address to be filled? I've tried the #required option, but it seems uneffective.

$form['question'] = array(
  '#type'     => 'radios',
  '#title'    => t('Do you prefer number 1 or 2?'),
  '#required' => TRUE,
  '#options'  => array(
    1 => '1',
    2 => '2',
  ),
);

$form['address_fieldset'] = array(
  '#type'  => 'fieldset',
  '#title' => t('Address'),
  '#description' => t('Please enter your address.'),
);
$form['address_fieldset']['address'] = array(
  '#type'     => 'addressfield',
  '#context'  => array(
    'countries' => array('FR', 'DE', 'CA'),
  ),
  '#default_value' => array(
    'country' => 'FR',
  ),
);

$form['submit'] = array(
  '#type'  => 'submit',
  '#value' => t('Submit'),
);
grantlucas’s picture

Allllrighty. Attached is a new patch which allows for setting it as required to work. Should've had that in there originally but just missed it. Yay reviews! So that works like intended now.

With the radio buttons, THAT is a weird one. I confirmed that when you have required radio form item which has no default value, then indeed the AJAX on the country selector breaks.

I have no idea as to what the solution to this is yet. In general though, with radio buttons, especially those which are required, you need to have a default value set. The form api itself has issues with required radios with no defaults and just gives "An illegal choice has been detected. Please contact the site administrator." as the error. Oh how that has eaten time trying to debug in the past.

So I'm not 100% sure if the radio issue is a non-issue since default_values should always be set on required radio buttons.

Thoughts?

Please re-apply this patch which now has the required flag. Would be great to get this fully tested for a release.

melissavdh’s picture

I am using the patch in #25 without any problems - thanks very much.

melissavdh’s picture

However, I cannot get the #states property to work with the form element. I have created a new issue for this here: http://drupal.org/node/1637364. Any help would be great :)

mikemiles86’s picture

Using the patch in #25 without any issue in a custom form.

cronix’s picture

Is there any planing about when this will be committed to DEV? This patch should help out to fix an issue with Commerce UPS: http://drupal.org/node/1313318

pfrenssen’s picture

Status: Needs review » Needs work

Have not tested it but have read through the code in #25, some remarks about the comment style:

Comments should end with a period:

  • + * Addressfield process function
  • + //Inject context defaults
  • + //Set tree to true
  • + //Restrict the country options to only those desired

In comments a space should follow the //:

  • + //Inject context defaults
  • +  //Set tree to true
    +  //Keeps submitted values together incase other form ites have similar keys.
  • + // Necessary for country_get_list().
  • + //Restrict the country options to only those desired
  • + //Set the element to required based on the passed in required flag

Typos 'incase' and 'ites':

+ //Keeps submitted values together incase other form ites have similar keys.

grantlucas’s picture

Status: Needs work » Needs review
FileSize
2.34 KB

I've attached the patch file with the corrected comment formatting.

alexgl’s picture

I have applied the patch in #31 and still am getting the error:

Notice: Undefined index: element_key in addressfield_standard_country_validate()

on line

$form_state['addressfield'][$address['element_key']] = array_diff_key($address, array('element_key' => ''));

is there a work around for this that I've missed in the comments?

my code is this

    $handlers = array('address' => 'address');
    $context = array('mode' => 'form');

    $addresses = $account->field_address;
    //where $account is from user_load

   $form['address_info']['address]['addressgen-address'] = addressfield_generate($addresses[LANGUAGE_NONE]['myaddress'], $handlers, $context);
generalconsensus’s picture

How do we go about getting this included in the next stable release? Might be important for folks like myself that have custom functionality that need this after the transition to 2.0. Thanks!

pfrenssen’s picture

@generalconsensus: If you want to help advancing this issue, you could do so by reviewing the latest patch. You can find more information on how to do this in Reviewing patches.

generalconsensus’s picture

I've noticed that when I create custom addressfield forms that the div id's are created dynamically (see the case here). How would I go about specifying them in my code or altering them in a hook function by default?

Here is my form creation code:

             $form[$x]['address'] = array(
              '#type' => 'addressfield',
              '#required' => TRUE,
              '#title' => t('Recipient\'s Address'),
              '#context' => array('countries' => array('AT', 'AS', 'BE', 'BG', 'CA', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'GU', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PR', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB', 'UM', 'US', 'VI'), ''),
              '#default_value' => array('country' => 'US'),
              '#description' => "Please enter the address you want to mail this gift to.",
              '#maxlength' => 60      
              );

Thanks

pfrenssen’s picture

@generalconsensus, use '#attributes' => array('id' => 'my-id'). For more information see Form API reference guide.

aacraig’s picture

There seems to be a bug in patch 31.

If you use the following to create the field:

$form = array(
      'my_address' => array(
        '#type'     => 'addressfield',
        '#title'    => t("Business address"),
        '#context'  => array('mode' => 'form')
      )
)

you get two errors.

The first is on line 309:

  if(!empty($form_state['addressfield'][$element_key])) {
    // Use the value from form_state if available.
    $address = $form_state['addressfield'][$element_key];
  }
  else {
    $address = (array) $element['#default_value'];
  }

which assumes that there will be a default value, which may or may not be the case.

The second is that the country select element is not populated. This is due to the unnecessary(?) call to drupal_map_assoc() on line 317:

  $countries = country_get_list();

  if(isset($element['#context']['countries']) && is_array($element['#context']['countries']) && count($element['#context']['countries'])) {
    $countries = array_intersect_key($countries, drupal_map_assoc($element['#context']['countries']));
  }

As country_get_list() will be used to populate $element['#context']['countries'] if not explicitly set in the form element configuration, it will already be correctly formatted as key / value pairs, and not a linear array, so array_intersect_key() returns an empty array. If you don't set #context => array('countries' => array('US', ...)) the following code works:

 $countries = country_get_list();

  if(isset($element['#context']['countries']) && is_array($element['#context']['countries']) && count($element['#context']['countries'])) {
    $countries = array_intersect_key($countries, $element['#context']['countries']);
  }

I think that indicates that if country_get_list() is used to populate $element['#context']['countries'] (as opposed to using the countries in #context) drupal_map_assoc() shouldn't be used.

The following code fixes the problem:

  if(isset($element['#context']['countries']) && is_array($element['#context']['countries']) && count($element['#context']['countries'])) {
    // see if this is a linear or hash array
    // if it's come from country_get_list(), the first key will be a string
    $test = array_keys($element['#context']['countries']);
    $country_hash = (is_integer(reset($test)))? drupal_map_assoc($element['#context']['countries']) : $element['#context']['countries'];
    $countries = array_intersect_key($countries, $country_hash);
  }

A workaround to avoid the #default_value warning is to set #default_value to NULL

Martijn Houtman’s picture

Patch #31 works fine for me. Would very much like this to make it into the current dev :-)

haleagar’s picture

Patch in #31 working for me, and I've started trying to use address field in the D7 pay module since it seems to still have a dependency on non d7 postal module, and needs a replacement such as this.
http://drupal.org/node/925354#comment-6783316

peterpoe’s picture

I have found that you can limit the available countries by simply providing the address builder some "fake" field instance information. This way, the option to hide the country select if there is only one country available will also work. Here is an example of a working implementation:

  $form['shipping_address'] = array(
    '#type' => 'addressfield',
    '#title' => t('Shipping address'),
    '#handlers' => array (
      'address' => 'address',
      'address-hide-country' => 'address-hide-country',
    ),
    '#context' => array(
      'field' => array(),
      'instance' => array('widget' => array('settings' => array('available_countries' => array('IT')))),
    ),
    '#required' => TRUE,
  );
peterpoe’s picture

We could then simplify usage by adding these two lines:

$element['#context']['countries'] = $countries;
+ $element['#context']['field'] = array();
+ $element['#context']['instance']['widget']['settings']['available_countries'] = $element['#context']['countries'];

So you could do:

  $form['shipping_address'] = array(
    '#type' => 'addressfield',
    '#title' => t('Shipping address'),
    '#handlers' => array (
      'address' => 'address',
      'address-hide-country' => 'address-hide-country',
    ),
    '#context' => array(
      'countries' => array('IT'),
    ),
    '#required' => TRUE,
  );

(some documentation in addressfield_element_info() wouldn't hurt)

ponies’s picture

I'm not sure if this belongs here, but when I change the country I get a 500 error saying that the custom validation function for the first element in the form can't be found. If the form is filled out without changing the country everything works.

Patch #31 is applied to 7.x-1.x-dev.

stewart.adam’s picture

This patch is based on #31 and includes a slightly modified fix for the first problem aacraig mentions in #37 (assumed default value) and the country list fix in #42. I omitted the code from the second fix (country list) in #37 as I could not reproduce the issue with the latest release of addressfield.

ponies’s picture

A follow up to my issue. The validation functions were in the include file and weren't available when the country was changed. I moved them to the .module file and that fixed my 500, but the country specific fields aren't replacing the default country fields.

ponies’s picture

#43 wasn't the fix for my issue. I ended up manually requiring the include file in the module.

knsheely’s picture

There are 2 spaces (&nbsp) being added to my form before the postal_code and administrative_area elements. I believe they are being added from the #prefix in the 'address' handler at $format['locality_block']['locality'] (line 59 of address.inc) and $format['locality_block']['administrative_area'] (line 82 of address.inc). Does anyone know how we can remove this prefix from the form? The following is my code for adding the addressfield form element.

$form['account']['field_address'] = array(
     '#type' => 'addressfield',
     '#title' => t('Address'),
     '#handlers' => array(
         'address' => 'address',
         'address-hide-country' => 'address-hide-country',
     ),
     '#default_value' => $address,
     '#context' => array(
         'field' => array(),
         'instance' => array('widget' => array('settings' => array('available_countries' => array('US')))),
     ),
     '#required' => FALSE,
 );
Primsi’s picture

Just tested the patch from #43 and it seems to work fine. Just a minor coding standard issue:

+++ b/addressfield.moduleundefined
@@ -276,10 +276,72 @@ function addressfield_element_info() {
+  if(!empty($form_state['addressfield'][$element_key])) {
+++ b/addressfield.moduleundefined
@@ -276,10 +276,72 @@ function addressfield_element_info() {
+  if(isset($element['#context']['countries']) && is_array($element['#context']['countries']) && count($element['#context']['countries'])) {

if (...)

And another side note: perhaps it would be good to add an example in addressfield_example.module?

illmatix’s picture

Patch #43 seems to work for me in Drupal 7.20

stewart.adam’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
2.58 KB

@illmatrix; glad to hear it works for you too!

@Primsi: good catch on the code style standards, thanks.

Attached patch is identical to #43 but with the two minor coding style fixes applied. I think these changes are minor enough to warrant marking this right away as RTBC given #48.

illmatix’s picture

How do you provide default values to this element type?

stewart.adam’s picture

Here's an example of use:

  $form['physical_address'] = array(
    '#type' => 'addressfield',
    '#required' => TRUE,
    '#handlers' => array('address' => 'address', 'address-hide-country' => 'address-hide-country'), // optional, used to extend default form, handler names are from the plugins/format folder
    '#context' => array('countries' => array('US')), // optional, used to limit to a single (or set of) countries
    '#default_value' => array(
      'thoroughfare' => '1234 Street'
      'premise' => 'Suite 35',
      'locality' => 'City',
      'administrative_area' => 'Province/State',
      'postal_code' => 'ZIP/Postal Code',
      'country' => 'Two-letter country code',
    ),
  );

The return format is a little bizarre and appears in its own address index under $form_state, I found what causes this but was not able to resolve it. Perhaps the module author can help us here.

illmatix’s picture

How come this field saves values in the root of $form_state and also $form_state['values'] ? Shouldn't it follow how other fields save values to the $form_state? I'm using #tree = true in this situation.

rszrama’s picture

It saves information in $form_state for use in form rebuilding when #limit_validation_errors is activated, meaning there would be no data in $form_state['values'] to use to preserve already entered address data if, say, the customer changed the country.

grantlucas’s picture

Patch #49 is good to go for me. I'm really hoping we can get this into the actual module sooner than later as we're now past a year since the first patch was submitted.

jurgenhaas’s picture

Not sure what's going wrong but I still can't submit the form after the user had changed the country. The way I'm building the addressfield is by using this code:

  $form['address'] = addressfield_generate(addressfield_default_values(), array('address', 'organisation', 'name-full'), array('mode' => 'form'));
  $form['address']['#tree'] = TRUE;

When I change the country and submit the form, the function addressfield_standard_country_validate() finds #default_value being different from #value and therefore sets $form_state['rebuild'] = TRUE; and I haven't found a way around that. Any help or advise is much appreciated.

grantlucas’s picture

@jurgenhaas I would advise that you make use of the form element this patch supplies as it builds everything for you. The method you show in #55 has issues and is why this form element was set up in the first place.

Check out #51 for an example of how to make use of the new form element and let us know if there's any issues with the patch.

Hope that helps you out.

jurgenhaas’s picture

Great, that did the trick. Problem solved ! Thanks a lot for your help.

Martijn Houtman’s picture

About #52 and #53: should the form element not save its input values in $form_values['input'], rather than in the root of $form_state?

jurgenhaas’s picture

Well, I found the values in $form_state['values']['address']['address'] where the form element in my case is called address too. I thought that was a pretty suitable location from my perspective.

grantlucas’s picture

I also have my results in form_state['values'] which is the proper place for submitted values to appear.

DaddyMacCadillac’s picture

Thanks for the awesome patch! Are there plans to include this in the next version? Thanks again!

rszrama’s picture

Yep, I'd like to put this patch in for the 1.0 release of Address Field. Just been waiting on something solid to test and the time to do it.

rszrama’s picture

Status: Reviewed & tested by the community » Needs work

Just a quick note as I review this - one thing that's obviously missing from the patch is the module's widget form hook was not updated to make use of the element. We won't want to be maintaining this exact same code in two different places. : )

stewart.adam’s picture

Status: Needs work » Needs review
FileSize
10.23 KB

Updated patch attached, changes since last patch in #49:

  • The addressfield form element no longer returns all elements within an address wrapper array
  • Function to get field's allowed countries has been split out of _addressfield_country_options_list() for better reusability
  • addressfield_field_widget_form() has been refactored to use the addressfield widget. Settings now are passed to the form element processor directly via $element or via the attached $context. The previously used element key format is preserved.
  • The behavior of $context['countries'] has been reworked a little bit to work such that an empty array indicates no limitations, but any values present will limit the available countries. Supported formats are a flat array of country codes i.e. array('US', 'CA') [for users supplying a context from a form element] or a identically keyed and valued array of country codes: array('US' => 'US', 'CA' => 'CA') [for when a field's allowed countries settings form returns this structure].

I have only done some light testing to make sure things are still working correctly, so feedback is required (and appreciated)!

Anonymous’s picture

After applying the patch in #64 I get this error:
Notice: Undefined index: #title in addressfield_element_process() (line 350 of /Users/doug/Sites/weathermaticOmega/sites/all/modules/addressfield/addressfield.module).

Anonymous’s picture

Sorry. Forgot to drink coffee this morning.

The problem was simply that I didn't add #title to my form.

stewart.adam’s picture

Thanks for mentioning it though, omission of #title should not produce an error anyways.

Also, I have been debating with myself if I want to try and find a way to eliminate the fieldset wrapper on the form element anyways and include it only in fields. The argument being that for a field that's the way it's been and should continue to be, but for form elements users may be embedding it elsewhere and can always include a wrapping fieldset themselves anyways.

What do you think?

muschpusch’s picture

I have two problems with this patch:

- it doesn't rebuild the form when choosing a different country. I used #51 but didn't add #context for limiting the country list
- the form doesn't render on the commerce checkout which could make rszrama unhappy

stewart.adam’s picture

Thanks for the feedback!

- the form doesn't render on the commerce checkout which could make rszrama unhappy

I've noticed this as well and tried working on it, the issue stems from the fact that a wrapping #fieldset was previously used around the addressfield elements, so in Commerce there is some alter hooks that attempt to remove that by looking 1 level deeper into the element tree. Of course, with the field element info hook we now have that all bundled as a single addressfield form API element, so those alter hooks end up skipping over (and thereby removing) the addressfield element itself.

I tried correcting this by adding a #fieldset wrapper in the field form builder, which would also resolve the problem I discussed in my earlier comment about giving form builders the option to include the fieldset themselves, as all users may not want the wrapping fieldset. However, when I attempt to do this the addressfield doesn't get rendered; I am at a loss for why. As far as I can tell, it would appear Drupal doesn't like rendering non-standard field types more than 1 level deep in a element tree in a field form builder callback.

Perhaps a code sample will illustrate this more clearly - after applying the last patch, this snippet starts around line ~525 in the field widget form builder callback, addressfield_field_widget_form():

   ...
      'delta' => $delta,
    );

    // This works, but we want a wrapping fieldset.
    // $element['#type'] = 'addressfield';

    // Wrap everything in a fieldset. This is not the best looking element,
    // but it's the only wrapper available in Drupal we can properly use
    // in that context, and it is overridable if necessary.
    $element['#type'] = 'fieldset';
    if (isset($element['#title'])) {
      $element['#title'] = $element['#title'];
    }

    // Here is what fails to render at all:
    $element['address']['#type'] = 'addressfield';
    // But strangely, setting the type to a non-custom field API type does
    // render as expected!?
    // $element['address']['#type'] = 'textfield';

    $element['address']['#context'] = $context;
...

I contacted rszrama to see what he thought about the issue but I think he's busy prepping for some upcoming conferences :)

- it doesn't rebuild the form when choosing a different country. I used #51 but didn't add #context for limiting the country list

I can't reproduce this one - after applying #64 and flushing my caches, it refreshes the country list as usual... Does it only fail to change the country if you do not supply a #context?

muschpusch’s picture

I can't reproduce this one - after applying #64 and flushing my caches, it refreshes the country list as usual... Does it only fail to change the country if you do not supply a #context?

It only fails with no #context when providing a context it works.

I get another error on a search API page:

Warning: array_intersect_key(): Argument #2 is not an array in _addressfield_country_options_list() (line 848 of sites/all/modules/contrib/addressfield/addressfield.module).

/**
 * Wraps country_get_list() for use as an Entity API options list.
 */

function _addressfield_country_options_list($available_countries = array()) {

get's passed "countries" only

stewart.adam’s picture

New revision of the patch attached. Changes:

  1. Added a new #inline property to the element that controls whether or not the address field form builder uses a 'fieldset' element as the wrapper (#inline = FALSE) or a generic invisible 'container' element (#inline = TRUE).
  2. Fixed the PHP warning when the #title property was not supplied
  3. Adjusted _addressfield_country_options_list() to create an one-element array if the argument passed is not an array

Also attached, for those wanting to use or test this with Commerce:

  • commerce_addressbook-addressfield_element_info-970048-71.patch: Fix form value replacement in the customer's address book drop-down
  • commerce_customer-addressfield_element_info-970048-71.patch: Fix display of address fields on checkout panes after migrating addressfield to the dedicated form element

I will be creating dedicated issues for each in the respective projects once this patch gets submitted, but in the mean time here they are.

Regarding the rendering problem from #69, turns out it was PEBKAC. I have a few testing addresses stored in Chrome so I don't have to retype them... Chrome's autofill unchecks the default "Address" handler when completing the form fields, so you end up with field with no handlers configured when saving. The address field was indeed rendering correctly, I had just inadvertently instructed it to display nothing.

It only fails with no #context when providing a context it works.

Does the attached patch revision help (please flush caches after patching)? If not, a code sample from your form builder function would be helpful... I'm still having trouble reproducing the issue. For reference, when I use this:

$form['myaddress'] = array(
  '#type' => 'addressfield',
  '#description' => "Please enter the address you want to mail this package to.",
  '#maxlength' => 60,
);

Switching from 'Afganistan' (the initial default) to 'United States' refreshes the form and then reveals the US state selector. Thanks for helping test!

I get another error on a search API page:

I installed Search API & Search API pages, configured it to index all of the addressfield elements with type "Fulltext" and I don't see any errors while searching - are you using a View with a exposed filter perhaps? Either way, change #3 in this patch will should fix the warning, but may not result in the functionality expected.

ibullock’s picture

Very happy to have found this thread. Patch from #71 is working well in my tests so far.

Chris Graham’s picture

Bit of an odd thing that I have noticed from using the patch in #71, I was using this code to output an addressfield on my form under an organisation fieldset:

$form['organisation']['address'] = array(
    '#title' => t('Address'),
    '#type' => 'addressfield',
    '#required' => TRUE,
    '#context' => array('countries' => array('GB', 'IE')),
);

The above works and sets the field to a default of United Kingdom as it is my default country in my install's location settings. However, if I do this:

$form['organisation']['address'] = array(
    '#title' => t('Address'),
    '#type' => 'addressfield',
    '#required' => TRUE,
    '#context' => array('countries' => array('GB', 'IE')),
    '#default_value' => array(
      'country' => array('GB'),
    ),
);

with my default country set to United Kingdom or Ireland it doesn't set the correct fields, it just fires out the addressfield default fields rather than location specific defaults. I even changed my location settings to US and removed the context above, as the default fields are the same as Ireland, but it still fired out the default fields rather than UK or US fields. I tried to manually fire the ajax to change the fields on form load by adding an #after_build to the element and used this function:

function MYMODULE_default_country($element) {
  //ajax_command_invoke('#' . $element['address']['country']['#id'], 'change');
  ajax_command_changed('#' . $element['address']['country']['#id']);
  
  return $element;
}

You can see both my attempts at invoking the change command, neither worked, the fields didn't change to UK fields. They do change when I switch between countries, so the ajax is firing on change, just not on form load and only when default values are set.

While I can live with this on this one form, I am probably going to need to switch between UK and Ireland on some other forms with addresses on them. Does anyone know why this is happening when you set default values?

ibullock’s picture

I've also noticed that on my installation when you edit the field is always loaded with the default country and its state/province field rather than the currently set value.

ibullock’s picture

Actually the field is always outputting Afghanistan in all states as the country on load. Something is wrong with how the default value is loaded maybe?

stewart.adam’s picture

with my default country set to United Kingdom or Ireland it doesn't set the correct fields, it just fires out the addressfield default fields rather than location specific defaults.

It looks like this is because you're supplying the default country as an array - there can only be one default value! The valid countries is an array, but the default country should be a string value. Using this works for me:

$form['organisation']['address'] = array(
    '#title' => t('Address'),
    '#type' => 'addressfield',
    '#required' => TRUE,
    '#context' => array('countries' => array('GB', 'IE')),
    '#default_value' => array(
      'country' => 'GB',
    ),
);

ibullock, perhaps the same issue is happening for you too? I tested creating a form (see above) as well as a field instance with a default country value set to GB and it worked correctly.

wmad’s picture

The example in #76 works for me with the patch in #71. However:

  1. If a default value is chosen for country, and the country field is hidden using '#handlers' => array('address' => 'address', 'address-hide-country' => 'address-hide-country'), it has to be hardcoded in the submit function.
  2. When the node is edited using the native drupal method (node/[nid]/edit), the country dropdown field is defaulted to Afghanistan instead of the submitted value.
stewart.adam’s picture

Thank you for testing the patch!

1. If a default value is chosen for country, and the country field is hidden using '#handlers' => array('address' => 'address', 'address-hide-country' => 'address-hide-country'), it has to be hardcoded in the submit function.

When using the following code (with the site's default country to Canada):

$form['organisation']['address'] = array(
    '#title' => t('Address'),
    '#type' => 'addressfield',
    '#required' => TRUE,
    '#context' => array('countries' => array('GB')),
    '#handlers' => array('address' => 'address', 'address-hide-country' => 'address-hide-country'),
    '#default_value' => array('country' => 'GB'),
  );

On submit I see:

Array
(
    [element_key] => organisation|address
    [thoroughfare] => 1234 Example Road
    [premise] => 
    [locality] => Town/City
    [administrative_area] => County
    [postal_code] => POSTCDE
    [country] => GB
)

I also tried without the '#default_value' => array('country' => 'GB'), and got the same output. How come it would need to be hardcoded?

2. When the node is edited using the native drupal method (node/[nid]/edit), the country dropdown field is defaulted to Afghanistan instead of the submitted value.

Sorry, I tried to reproduce this but was unable to confirm the issue. I tested using the following steps:

  1. Clean D7 install
  2. Install & patch addressfield with #71
  3. Create new content type and add a Postal Address field to it
  4. Configure the field with United States as default country, check handlers Address Form and Hide the country when only one is available, limit to 1 value
  5. Save & create a new node
  6. On the node edit page I saw the US fields. What are your field's settings? Maybe it is triggered by a particular setting.

tien.xuan.vo’s picture

This patch fix these errors:
1. Missing country in add/update node page.
2. Notice: Undefined index: default_value in addressfield_standard_country_validate().

Note: No need to apply #6's patch from #1508162: Issue with addressfield in multiple value field collection combined with File fields

Artusamak’s picture

The patch #79 combined with #1263316: Configurable non-empty value conditions - #66 are working fine for me.

The patch looks nice.

JKingsnorth’s picture

I second Artusamak's comment - #79 and #1263316: Configurable non-empty value conditions #66 solved my the problem with multiple addresses spawning lots of blank addresses.

Johnny vd Laar’s picture

Artusamak’s picture

Please add interdiff for readibility in order to ease the review process, thanks!

jibran’s picture

+++ b/addressfield.module
@@ -288,10 +288,91 @@ function addressfield_element_info() {
+  // the form settings supplies can return its usual identically keyed and valued

80 char limit.

rszrama’s picture

There are at least a couple of things I don't really like in this patch:

  • Extending the "context" array to include element settings. As is, the context array relates to the context in which the field will be displayed (i.e. field location / display mode), but by putting the countries setting in there, we're also making it about how to build the form itself. Why not just add a #countries property to the element alongside the #handlers array?
  • Adding the new #inline property; that's not a very descriptive name. Why isn't it just #wrapper_type or something? The boolean isn't very descriptive, but "container" vs. "fieldset" is self-explanatory. Honestly, this feature is really out of scope for the current issue; I think I'd prefer to see this as a follow-up feature request.

I also don't get why this is being removed:

-  // If the country was changed, rebuild the form.
-  if ($element['#default_value'] != $element['#value']) {
-    $form_state['rebuild'] = TRUE;
-  }

I don't see any corresponding addition of code to replace that. Any ideas?

jurgenhaas’s picture

josebc’s picture

Hello
Im using addressfield with commerce and after applying the patch addressfields in the checkout panes disappeared

meecect’s picture

I'm very interested in this work. It seems to be working for me after applying patch in #82. I was wondering, are there any validation helpers available if I use this method, or will I need to do my own validations?

thanks,

Cliff

smiletrl’s picture

@ Josebc, I got the same issue too. However, if I add two address fields, both address fields work well in check out page. Not have much time to investigate this, so here is a quick solution:

/**
 * Implements hook_form_FORM_ID_alter().
 */
function product_display_form_commerce_checkout_form_checkout_alter(&$form, &$form_state, $form_id) {
  // There's a bug for address field after applied this patch #79 from
  // https://drupal.org/node/970048. The address field will disappear from
  // the checkout page.
  // Hard-coded the address field type.
  if (isset($form['customer_profile_billing']['commerce_customer_address']['und'][0]['#type'])) {
    $form['customer_profile_billing']['commerce_customer_address']['und'][0]['#type'] = 'addressfield';
  }
}

tthenne’s picture

Has anyone been able to troubleshoot #87 issue with the address field disappearing on the Checkout page? This is an issue with the address field disappearing on the checkout page after applying the patch.

tthenne’s picture

After reading the thread closer it looks like you have to apply the commerce_customer-addressfield_element_info-970048-71.patch in #71 as well to patch the commerce_customer.checkout_pane.inc file as well and the address field will show up.

Thanks for the patches!

Andrew Schulman’s picture

I applied the patch in #82 and put an addressfield in the site-wide contact form. Mostly it works, but what I notice now is that when I change the country field, say from US to CA, the address fields are only updated (e.g. "State" should change to "Province") if I'm logged in. For anonymous users, the address fields don't change for the new country. Does anyone else see this behavior? Any ideas as to why?

Andrew Schulman’s picture

A little more about #92: When an anonymous user changes the Country selection:

  • No POST data is sent to /system/ajax.
  • The Drupal log records an error:
    • Type: ajax
    • Severity: warning
    • Location: /system/ajax
    • Message: Invalid form POST data.
Andrew Schulman’s picture

Hm, #92 looks like a bad interaction with the Botcha module. Disabling Botcha fixes it. Please ignore for now until I can track it down further. Sorry for the noise.

RogerRogers’s picture

EDIT: This comment isn't useful to this thread so I'm blanking it. The issue was in my code.

xpersonas’s picture

Subscribe

leolandotan’s picture

I used the patch at #79 (https://www.drupal.org/node/970048#comment-7753021) and it's working but when I try to use hook_form_alter to add a placeholder, the Address 1, Address 2, Country, State, City/Town, and Postal code fields are not in the $form array. It just displays the original Addressfield declaration.

Any thoughts on this?

bojanz’s picture

Status: Needs review » Postponed

This will need to wait for the 2.x branch, it's too big to be made to the 1.x branch at this point in time (and hard to justify since it's a feature request).

Thank you everyone for your work so far.

jcisio’s picture

Could we add the 2.5 KB patch in #49 then refactor everything else in 2.x? It would be the same amount of work, or even easier because half work is done. The form element is quite self-contained.

SocialNicheGuru’s picture

this patch produces errors in other modules like addressfield_autocomplete that use the addressfield structure.

arijits.drush’s picture

This code snippet will help up to add address field inside form api

$address_form = $form;

 field_attach_form('user', $entity, $form, $form_state, NULL, array(
   'field_name' => 'field_register_address',
   ));

$form['issuer_register']['address'] = $address_form['field_attach_form'];

Here

user is entity, you can change it if your address field use is node

field_register_address is machine name of address-field, change it accordingly

stewart.adam’s picture

I have attached an updated patch against addressfield 7.x-1.1.

@rszrama, the #inline property is gone from this patch as the use case I intended to use it for is not longer applicable with the 7.x-1.1 code. I have also moved the available country list away from #context['countries'] and into its own parameter #available_countries.

@bojanz, I hope you can reconsider this feature request for inclusion with 1.x with this simplified patch - it helps tremendously for custom modules looking to integrate addresses into forms and 7.x-2.x seems far away without it having a branch in git yet.

Ayesh’s picture

Thanks Stewart for the patch in #102. However, it did not use the #title property, which isn't really working for my case. I think others too. Also, the widget doesn't seem to play nice with #required.

Attached are rerolls of the patch in #102, along with some improvements that were addressed in patches up to #83. Also attached an interdiff.

hargobind’s picture

It's nice to see the ball rolling again on this :)

I ran into the #required bug as well, so thanks @Ayesh for your edits. I have another fix to add:

Although many people will choose this way to create the field:

  $form['mailing_address'] = array(
    '#type' => 'addressfield',
    '#title' => t('Mailing Address'),
    '#required' => TRUE,
    '#default_widget' => 'addressfield_standard',
    '#default_formatter' => 'addressfield_default',
    '#default_value' => array('country' => 'US'),
  );

It's also possible to attach the field if you have a fieldable entity using field_attach_form():

  field_attach_form('example_entity_type', $entity, $form, $form_state, NULL, array(
    'field_name' => 'field_mailing_address',
  ));

This method will create the field using the field settings UI where you can limit which countries are available, what the default country is, whether the field is required, etc. To make sure the #required property was respected, I added a check for $element['#context']['instance'].

@Ayesh: FYI, your patch contains the full Drupal path (a/sites/all/modules/addressfield/addressfield.module), and so it won't apply cleanly for cases where modules are stored in a different folder (e.g. /sites/all/modules/contrib/ or /sites/[site-name]/modules). In the future, you can manually just strip out the path if you need to before submitting your patches.

hargobind’s picture

Fixed the patch names from my previous comment.

I'll see if I can make time in the next few days to look at the conflict with the addressfield_autocomplete.module as reported by @SocialNicheGuru.

stewart.adam’s picture

@hagobind, can you detail the use case for using field_attach_form() over the addressfield form element? I can see why it would be required without this patch, but in my opinion that function was meant only to be used internally by the Field API on entities. If there's any functionality missing from the addressfield FAPI element type that field_attach_form() has, I think we should work on augmenting the form element's functionality instead.

If I've misunderstood and this additional verification fixes the required setting on fields, then great! But for the record, I do not think we should advocate attaching addressfields to a form using field_attach_form() with this patch is applied. Implementing the addressfield as a form element precisely is so that people can embed addressfields without relying on internal function or creating dummy fields with different settings for each addressfield configuration they'd like to embed on a non-entity form.

Concerning #required and limiting countries, the following should achieve what you need:

  $form['mailing_address'] = array(
    '#type' => 'addressfield',
    '#title' => t('Mailing Address'),
    '#required' => TRUE,
    '#available_countries' => array('US', 'CA'),
    '#default_value' => array('country' => 'US'),
  );
Ayesh’s picture

Thanks hargobind for the patches. A country-specific address field input element would be an awesome addition, so I'll try my best to get this issue passed.
I've hidden my recent two patches because the #105 seems to work well. Sorry that my patch contained the fool path. I have the entire project in git, and I just diffed without realizing it.

If others can test the patches and provide feedback/patches, that would be really helpful.

pfrilling’s picture

I applied the patch in #105 and successfully added a new addressfield form element to my custom form. So far, everything seems to be working correctly. Great job!

hargobind’s picture

FileSize
70.86 KB

@stewart.adam I didn't realize that field_attach_form() was considered an "internal" function. My particular use case is that I have been building a lot of forms lately to add/edit fieldable entities. Sometimes I want to attach all the fields and make small modifications, and other times I just want to grab specific fields that already have the entity's values loaded. Either way, I find it's nicer (and easier) to customize the settings of each field (etc. title, description, default values, etc.) using the Manage Fields UI and drop the fields into my form with field_attach_form() rather than coding all the fields from scratch. Is this approach wrong or bad as far as what those functions were meant to do? I'm happy to hear a better way to do things.

Secondly, this patch introduces a bug when using the Manage Fields UI to attach a field to a node (or entity for that matter) which I was unable to track down after 2 hours of looking through the code. If you create an address field on a node type via the Manage Fields UI, then go back and change the default country, the country is stuck to the value it was set to when the field was first created.
Steps to reproduce:

  1. Set a default country at admin/config/regional/settings
  2. Create a new address field on the node type of your choice, and walk through all the steps to save it until you get back to the Manage Fields page.
  3. Edit the field, change the country to something else, and save the field.
  4. Create a new node of that type and notice that the default country is what the site's country was set to when you first created the field.

This appears to be an issue with how the field data is stored in {field_config_instance}. See the attached image for an unserialized version of my test field's "data" column when printing the value of $element inside of addressfield_element_process(). You can see there are two values that store the country:
- $element['widget']['settings']['default_country'] - this value correctly changes each time the field is edited.
- $element['default_value'][0]['country'] - always contains the site's country value when the field was first created.

I think a good solution would be to eliminate $element['default_value'] since none of it's sub-values are useful in regards to the field configuration. But I'm not sure how to do that.

And lastly, I tried looking at the integration with addressfield_autocomplete.module as reported by @SocialNicheGuru in #100 but had no luck. I have a feeling that it's because of how the element in this patch is nested whereas the element in the original module is not (or at least not in the same way).

Ayesh’s picture

The address field element is nested inside a fieldset because that way, you can add a title, description, etc.

stewart.adam’s picture

@hargobind, although there are no explicit visibility on the functions, field_attach_form() is from the file field.attach.inc and used to embed the form elements of a single field onto an entity form - it's not 'bad' to use it, but it's intention was not for use on custom forms with the form API. As you mention it might suit your use case if you're dealing with entities, but the addressfield is not available from the form API using that method of form generation and is what this patch is attempting to address. Also, note that using field_attach_form() does not require this patch and would work fine with the stock addressfield module.

Regarding the bug - thank you for reporting it, I'll try to reproduce it shortly.

As for integration with addressfield_autocomplete and other contrib extension of addressfield: unfortunately this patch likely breaks them - it's one of the reasons the maintainers don't want to commit it to the existing 1.x branch. Any module that depended on using a form_alter hook to alter the addressfield (as previously the forms were exclusively generated using field_attach_form()) will break, and will need to be adjusted to alter the new addressfield FAPI element declared in the patch instead.

dsdeiz’s picture

On my end for some reason, even if I don't have #required => TRUE for the form element, it would still make each of the fields required.

Sorry, never mind. I just realized that if an addressfield is not required, it would rather show a select form element and have a default value set to "None". I had a default value set to array('country' => 'US'). This doesn't go well when the addressfield form element has '#required' => TRUE.

sagannotcarl’s picture

The patch in #105 didn't apply cleanly to the current dev. Here is a version re-rolled against the current dev version.

hargobind’s picture

Fixed a bug with the views filter when filtering by Country. This patch is a reroll of #113 with the addition of a change to views/addressfield_views_handler_filter_country.inc.

leendertdb’s picture

Thanks everyone for all the hard work on this issue. I applied the patch in #114 and it all seems to be working great, exactly what I needed.

I think this will be a great addition for the 2.x branch, makes this module a lot more flexible.

efruin’s picture

I applied the patch in #114 and so far it's working well for me. Thanks to everyone that has put in time on this.

Anonymous’s picture

Patch in 114 seems to break #1979794: If only one available country is selected administrative area/postal_code text boxes do not show on addressfield widget forms on content types. A workaround is to go ahead and select a default country even if you only have one available country selected. I don't know if I'll be able to provide a patch anytime soon because I currently have other pressing client work to tend to.

Beakerboy’s picture

I am using patch 114 within a custom module where I have an address as part of the module's admin configuration. It seems to be working fine. My next step is, I plan on creating a sub-entity where every entity will have an optional address.

Ayesh’s picture

Rerolling the patch just in case.
This is based on #103 patch, but with some minor changes (mainly around _addressfield_country_options_list()).

Ayesh’s picture

FileSize
14.35 KB

That old patch has a bug that it did not set the #required properly.

Ayesh’s picture

FileSize
14.36 KB

Terribly sorry. 119 and 120 both have wrong patches. This should do it.

rlangille’s picture

Tested #121 and it seem to be working quite well for me. Thanks to everyone who put time in on this!

N20’s picture

#121 works for me as well. Thanks for the effort.

stewart.adam’s picture

This is great - #121 is working well for me too. Looks like this is stabilizing!

I've hidden a few of the older patch sets (keeping the last patch version from each of the last few authors) to reduce clutter in the notifications.

Anas_maw’s picture

#121 cause an error with views filter: "Warning: array_flip(): Can only flip STRING and INTEGER values! in _addressfield_country_options_list() line 979 of addressfield.module"

this patch solve this error by fixing views handler (addressfield_views_handler_filter_country.inc)

Ayesh’s picture

Could you post an interdiff as well, @Anas_maw?

Anas_maw’s picture

FileSize
678 bytes

Here is the inerdiff file.

jibran’s picture

Here are some review points.

  1. +++ b/addressfield.module
    @@ -330,10 +332,86 @@ function addressfield_element_info() {
    +  if (!empty($address['country']) && !in_array($address['country'], $element['#available_countries'])) {
    +    unset($address['country']);
    +  }
    

    Why not generate error instead of setting it to default?

  2. +++ b/addressfield.module
    @@ -330,10 +332,86 @@ function addressfield_element_info() {
    +  else if (isset($element['#required'])) {
    +    $element['address']['country']['#required'] = isset($element['#required']) ? (bool) $element['#required'] : FALSE;
    +  }
    

    This is automatically handled by form api. No need for this here.

  3. +++ b/addressfield.module
    @@ -330,10 +332,86 @@ function addressfield_element_info() {
    +    $element['address'][$key]['#parents'] = $element['#parents'];
    +    $element['address'][$key]['#parents'][] = $key;
    

    This is also handled by form api.

  4. +++ b/addressfield.module
    @@ -411,14 +485,34 @@ function addressfield_default_values($field, $instance, array $address = array()
    -  drupal_alter('addressfield_default_values', $default_values, $context);
    

    Are we sure that we want to lose the alter functionality?

jantoine’s picture

I'm noticing that the patch from #125 is adding double fieldset wrappers to entity fields of type addressfield.

Mchraiet’s picture

Category: Feature request » Support request

Hi,
since patch addressfield_define_and_use-970048-125.patch, I cannot change the #required value.
For now, the path to go to the #required value is:
$form['field_billing_register']['und']['profiles'][0]['commerce_customer_address']['und'][0]['country']['#required']
And then I can set TRUE or FALSE.
Is there something that changed for that ?
Thanks!

jphelan’s picture

@jantoine - I get two as well. If I comment out line 102 from the patch I only get one and everything seems to still work.

//$element['address']['#type'] = (isset($element['#inline']) && $element['#inline'] == TRUE ? 'container' : 'fieldset');

maciej.zgadzaj’s picture

The following code in addressfield_element_process() (patches #121 and #125) breaks VBO's Modify entity values action for entities which have a required addressfield in them:

+  // Set the element to required based on the passed in required flag.
+  if (isset($element['#context']['instance']['required'])) {
+    $element['address']['country']['#required'] = (bool) $element['#context']['instance']['required'];
+  }
+  else if (isset($element['#required'])) {
+    $element['address']['country']['#required'] = isset($element['#required']) ? (bool) $element['#required'] : FALSE;
+  }

VBO unsets #required value when rendering form elements for fields, so in addressfield_element_process() the $element['#required'] is FALSE, but then all address sub-fields are set to TRUE anyway as the $element['#context']['instance']['required'] is TRUE.

It works fine again after replacing the above chunk of code with just:

$element['address']['country']['#required'] = isset($element['#required']) ? (bool) $element['#required'] : FALSE;

I did not follow the whole logic of the new code, so please forgive my question - but why do we need to check the $element['#context']['instance']['required'] value?

joelstein’s picture

We should not change the parameters for addressfield_default_values(), since other modules will be sending $field and and $instance to it (notably, Commerce Stripe).

Instead, let's keep this function name for that use case, and introduce a new function called addressfield_element_default_values(). That's what this patch does.

I haven't addressed any of the other points in the previous comments.

hargobind’s picture

+1 for @joelstein's suggestion in #133 for having a different function name for addressfield_default_values() instead of overwriting the existing one. Another prominent example is the commerce_paypal module which uses the function signature of addressfield_default_values($field, $instance).

hargobind’s picture

Including a patch based on #133 to fix the double fieldset wrappers mentioned in #129 and #131.

I made a change to addressfield_field_widget_form() where I added a flag in the #context array of the addressfield element called has_parent_widget_container. Then inside of addressfield_element_process(), this flag is checked alongside $element['#inline'] to determine the FAPI type of container or fieldset.

All the previous points still need to be addressed.