We have a content type with the address field. The address entry is optional. When a user decides not to provide an address, the default country is saved to the node. It would be desirable to provide a null value by default. Would it be possible to provide an inline button that would add an address field to the node, rather than having the country and address fields displayed by default?

Proposed resolution

This issue contains a patch using hook_field_presave().
The preferred way is to use hook_field_is_empty(), to determine if an empty/default value should be stored in the database.
However, hook_field_is_empty() does not contain info about the field instance settings. See #1489484: Add $instance parameter to hook_field_is_empty().

Comments

brylie’s picture

Priority: Normal » Major

I am working on a directory of organizations. Most of the organizations have addresses, or a country of origin. However, some organizations do not provide such information.

I would like to omit the address information on some nodes. Even with the address field being optional, there is no way to omit the country field. I have not selected a default country, so Afghanistan is the automatic selection.

Please provide the option (default or otherwise) to omit a country field.

brylie’s picture

This problem becomes more complicated when allowing multiple addresses to be entered on a node. By default, the address field is rendered with two automatic address field entry widgets featuring the default address settings. Now, every node that I enter has an additional address, with the default address settings, even though there may be only one primary address.

E.g. I am making a local directory for Olympia, WA. I have set the default address form parameters to be Olympia, Washington, USA. I have also enabled multiple addresses to be used, for organizations with multiple locations. When I enter a new location, it has multiple addresses, one primary mailing address and another generic address "Olympia, Washington, USA."

brylie’s picture

Category: feature » support
cristian100’s picture

Subscribing, this is very annoying, each time a user edits a node, a new entry for the address is populated just with the default country.

sheldonkreger’s picture

Even if the other address fields are required, we should be able control the requirement of the country field.

pounard’s picture

This is more than annoying, this is a real bug.

  • For example if you attach a geofield based on an addressfield, and the user leaves the address empty, the country information will be saved and address not considered as empty, which will make an arbitrary map appear centered on the country.
  • Same for every possible check the field API could make using the hook_field_is_empty().
  • It also consumes useless database space by inserting almost fully empty rows in the fields tables.
pounard’s picture

StatusFileSize
new1.73 KB

Here is an ugly patch working for my use case (read and use it wisely before using it).

sheldonkreger’s picture

#7 just cleans up existing empty address fields, it doesn't prevent any more from being created, correct?

pounard’s picture

The presave hook implementation actually avoid the field_(base|revision)_* rows to be created too.

johnv’s picture

FYI, the following comment gives an alternative implementation: #968112-111: Allow addressfield to be optional
but current patch with hook_field_presave() is better then hook_node_presave() or hook_entity_presave().

johnv’s picture

Title: Optional address field, omit country » Make Addressfield optional, (even if country is required)
Status: Active » Needs review
StatusFileSize
new1.05 KB

Attached patch is reworked from #7.
It still uses hook_field_presave(), which now checks against the default value from the field instance.

There was no need anymore to change hook_field_is_empty().
FYI, see also #1489484: Add $instance parameter to hook_field_is_empty() , which is prerequisite for doing this properly in hook_field_is_empty().

johnv’s picture

#11 did a weird thing when the default field instance value contains not only Country. Correcting that.

sheldonkreger’s picture

Status: Needs review » Reviewed & tested by the community

Patch in #12 allows me to save nodes with no address info other than the country, when the field settings are configured correctly (address field is optional). It still sets up a DB entry with null values, other than the country field. Whether that's a good thing or bad, I'm not sure, but it was mentioned in #6.

giuvax’s picture

I know this is really ugly as workaround but I gave up finding a solution with empty saved profile because of mandatory country field. I'm tired of searching solutions.
So I decided to create a rule, and here it is:


{ "rules_address_field_wtf_solution" : {
    "LABEL" : "Address Field WTF solution",
    "PLUGIN" : "reaction rule",
    "REQUIRES" : [ "rules", "entity" ],
    "ON" : [ "commerce_customer_profile_insert" ],
    "IF" : [
      { "data_is" : { "data" : [ "commerce-customer-profile:type" ], "value" : "billing" } },
      { "data_is_empty" : { "data" : [ "commerce-customer-profile:commerce-customer-address:locality" ] } },
      { "data_is_empty" : { "data" : [ "commerce-customer-profile:commerce-customer-address:postal-code" ] } }
    ],
    "DO" : [ { "entity_delete" : { "data" : [ "commerce-customer-profile" ] } } ]
  }
}

I put two conditions just to be sure.

mrfelton’s picture

Status: Reviewed & tested by the community » Needs work

#12 works well for me too, bar the empty database entries. I'm setting this back to needs work because of the issue with saving blank data.

johnv’s picture

FYI: Patch #12 contains a correction for element_key.
That part may be a duplicate of #1928166: element key didn't use parents element and override default item with field collection

johnv’s picture

Status: Needs work » Needs review
StatusFileSize
new1.95 KB

Attached patch should deal with #6, too.

the issue with saving blank data.

mrfelton’s picture

Same patch as #17 but without the extra whitespace

rudiedirkx’s picture

Status: Needs review » Needs work

Comparing an item to the instance defaults is bad logic. It's bad for two reasons:

  1. submitting a default doesn't mean it's not a value: it should still save
  2. if you remove a field value from the default, it now saves (because it's different)

I changed it to compare field names of non-empty fields, to fix bug # 2, but that's also faulty, but it still removes items with the same value as the default value.

Time allowing I'll create a good patch today. Maybe tomorrow.

johnv’s picture

@rudiedirkx, I don't understand your point. This issue is exactly to resolve the 2 points you mention:
- Addressfield comes with a prefilled, required subfield 'country'. Submitting this should NOT generate a db-entry
- changing data from the default implies that the user has thought about the new, better input, and SHOULD result in a db-entry.
Indeed, this behaviour might be different from a 'normal' field, but it all stems from the Addressfield's premiss, that the country is prefilled and required.

rudiedirkx’s picture

@johnv Don't use the default value to check for the Country field. Only Country is special. You can have defaults for the others. If have a City in default and submit, it should save that. If you'd remove the city, it shouldn't submit that, because only the Country is (pre)filled and the rest is empty. The last patch checked for difference, so if you have a default City (and Country, hidden) and you remove that City, it would save the empty (except for Country) item.

So the fix should check:

if ((only the country is non-empty AND the 'hide country' option is ON) OR (everything is empty)): don't save

The default value is irrelevant, because the default value includes all other fields too (2 streets, postal, city).

Right?

johnv’s picture

@rudiedirkx,
I don't agree with: If have a City in default and submit, it should save that.
I agree with: If you'd remove the city, it shouldn't submit that,
Perhaps it changes on the use case.
More opinions are welcome!

manuel garcia’s picture

This is indeed a tough one to figure out... let me try to analize the problem see if we can organize our thoughts.

The default country is used mainly for when the field is only going to get addresses from a certain country, so we set a default value to save time and clicks for the content creators. I believe this is pretty much the use case.

The problem comes when the address field is optional. This means that the content creator does not want to want to HAVE to enter an address in order to save the content. Currently this saves an emtpy value for everything except for the country, which is not what the content creators expect/want.

I suppose the same can be said for the rest of address fields.

The problem comes from address field being really a "multi-fields-field", and what I think we need is a set of configuration options (per field in address filed?):

"Set a default value for this field" and then two sub-options:
-- "If the others are empty, don't save the field's data if it is on default value"
-- "Save the default value regardless of the rest of data entered."

To me this seems a bit messy perhaps, but this is the situation we have, any other ideas?

mxt’s picture

What Manuel Garcia proposes in #23 make sense to me: +1 for this solution.

giuvax’s picture

I agree with Manuel Garcia's #23.

rudiedirkx’s picture

#23 seems complex... Why not handle defaults as all other Drupal fields do? If you don't change the default and submit (and the item isn't empty), it's saved. The only special thing in this case is the country field. If all other fields are optional (and only the country relevant), the 'address-hide-country' option will never be ON, so we have to check that option.

This function does that:

<?php
function addressfield_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  $implicit_country = !empty($instance['widget']['settings']['format_handlers']['address-hide-country']);

  foreach ($items as $delta => $item) {
    // Eliminate unnecessarily differentiating elements, before comparing $item and $default.
    // 'element_key' contains an index, which corrupts comparing multivalue fields.
    unset($item['element_key']);

    // Ignore 'country' if that's implicitly set by the 'address-hide-country' option.
    if ($implicit_country) {
      unset($item['country']);
    }

    // See if any other fields are filled, by default or manually. If not, remove this item.
    $item_filled = array_keys(array_filter($item));
    if (!$item_filled) {
      unset($items[$delta]);
      unset($entity->{$field['field_name']}[$langcode][$delta]);
    }

    // Also remove the parent, if no addresses left.
    // This shouldn't be necessary, since 'normal' empty fields still contain
    // this complete entry. But while testing, the node-view page still shows.
    if (empty($entity->{$field['field_name']}[$langcode])) {
      unset($entity->{$field['field_name']}[$langcode]);
    }
  }
}
?>

It allows an item with JUST the country filled IF the 'address-hide-country' option is OFF. (Which makes total sense to me, otherwise you'd submit a completely empty form and expect it to save, which is weird IMO.)

I don't have time to roll a patch against dev or stable. Try it out and roll it.

pounard’s picture

The problem is user experience, if a user does not care about the address, he wont empty it manually, makes no sense to ask a user to do that. IMO defaults should never be saved for an address if the user don't want to input it. I think the algorithm should be: if no fields have been changed, nothing should be saved, if one or more values have been changed, everything should be saved. From the user point of view, I think it's the expected behavior.

phiscock’s picture

But if it doesn't save if nothing has changed then in a scenario where the correct entry is the default country it wouldn't save when the user could realistically expect that it would.

From my perspective the logical answer is to be able to offer the option of the country field being empty or "none" country option that saves as empty. That offers the most flexibility to both administrator and user to choose what result they get from the form.

rooby’s picture

There are legitimate use cases where you would want the default value to always save unless manually emptied, and there are use cases where you would not want that.

pounard’s picture

Then this can be an instance level setting, or widget setting? It's possible implement multiple behaviors, but at least these:
+ One which cares only about required fields (country) and does not save if this specific value is default and other are empty (which is actually #23 if I understood it well)
+ One which cares about all default values, and does not save when all values are default
+ One other which keep the default stupid behavior
+ Any other suggestion?
And leave the site builder choose whatever behavior he wants.

manuel garcia’s picture

We cannot save the country alone, this results in problems later on when trying to build maps out of this content, etc. Unless that's the only thing you want to record in your field I suppose.

This problem is indeed complex, perhaps we should make a list of usecases / configuration posibilities and take it from there? @rudiedirkx I'm not sure I can follow what you said... sorry! :S

  1. Mandatory address field
    • Default country selected: save always
  2. Optional address field
    • Default country IS ENFORCED (not good): Options
      1. Save ONLY if ANY of the rest of fields does NOT have the default value submitted
      2. Save always

Coming to think about it I believe the problem arises from the fact that we are forced to select a default country even if the field is set to optional. So perhaps we should tackle that? If we could select no country as default when the field is optional, we would not be saving address fields with just a country in it....

rudiedirkx’s picture

Status: Needs work » Needs review

All the edge-case configuration is unnecessary IMO. If the site builder really wants something special, they can alter and validate stuff. They can even add a field_presave. Addressfield should go with ONE method (a strict method IMO, so no empty or almost empty stuff is stored) and leave specificities up to the site builder. You can assume they know a little bit of Drupal and PHP to 'fix' that. You can never get ALL use cases in configuration, so you shouldn't try any.

@Manuel Garcia You can save an address with just a country. And you should. A country might be all that's relevant. If that's the case, the 'address-hide-country' will be OFF (otherwise the form would be EMPTY), so my solution would work.

You should try my solution (sorry, no patch today) and try every use case (including defaults) you can think of. If it breaks, let us know, so we can specify. No point in mapping out ALL use cases. It's impossible to program and impossible to understand (for site builders).

deanflory’s picture

Yeah, I just need my addressfields to stop adding additional ones each time the entity is edited and saved with the required default country since there is no "none" in the default form setup. Just add a - None - in the default form just like in the actual entity form. I've read all these alternate uses/configuration comments in multiple issues and can't fathom why it's so difficult to have this field act like pretty much every other field in it's default state, then just add optional checkboxes with other settings for those edge cases. Why the discussion? I know that sounds rude and/or novice but I'm confused why a default state across the board shouldn't apply to this field also unless it's manually set to be required as a form field. #overthinkingit

rudiedirkx’s picture

@deanflory Because you must be able to set a non-empty default and since there's an option to hide the non-empty country field, that should sometimes be ignored. Your use case might be simple, but getting them all is apparently the goal.

deanflory’s picture

You mention "must be able to set a non-empty default" but isn't that an "able" and not a "have to"? Did a miss the point why a country is required, default or selected?

Isn't the "option to hide the non-empty country field" for sites based in one country and not for providing a default "- None -" so defaults don't continually add additional addresses?

I apologize if I'm completely missing the sticking point here and wasting everyone's time trying to wrap my head around this.

rudiedirkx’s picture

I don't understand. There's no "have to" in "must be able to set a non-empty default". If you mean the "must be", it absolutely is must be. The only issue IMO is to check the hidden Country field. Solution (not patch) in #26 does that.

Alright, I'll create the patch.

rudiedirkx’s picture

Attached patch does exactly #26. It's rolled against stable, so might not apply to dev? (Function added to the very end of the module file.)

I don't know how to enable the country to have an empty default value (for if you can't use the 'address-hide-country' option). The ctools plugins are very weird, without values and field instance config to check.

What it should do is enable you to set the default (in the field instance config) to an empty country and then create all new address widget with an empty country. I've no idea how. Adding #empty_option to $format['country'] in addressfield_format_address_generate() isn't enough.

Attached patch is perfect for if you have only 1 country, but not if you allow several, I understand now. Sorry.

deanflory’s picture

Here are the problems I'm seeing now:

1) Country is still required in the default field settings, there is no "- None -" option which would allow the field to be completely optional and not save an address if no country or other address fields are selected/filled-in. In all these comments people keep saying "country is required" but I haven't seen one comment that steps out of that small box and says. Someone asks "why is country required" and someone immediately answers "because Drupal already expects it to have a value". Other fields don't require a default setting that has actual saved data like a specific country, they can be empty (which may be a saved value but that's what I'm getting at here). If I set up a text field that isn't set to be required, and the user doesn't fill in anything, that field doesn't have a presentable value, can thus be set to be hidden if it has no value and then not show up at all, field data or label.

2) The edit entity form widget does allow a "- None -" now (can't remember if this is with a patch or not, thinking it was applied to the latest dev). While this helps, it requires every user on every submission that has an addressfield to manually set it to "- None -" or else whatever the default country is, it will save it as such. So this dumps the problem on the end user which in turn, due to end user laziness or oversight, still makes the country required in the real world and thus adds a 1st and 2nd address entry since it always displays 2 sets of addressfield fields (multiple instances).

I'm unsure why it was set-up to allow "- None -" on one but not on the other, seems like the default field settings were overlooked as another instance of where "- None -" should have been applied as an option. Or maybe it doesn't show up for an existing field?

In case my use case clarifies my viewpoint: I have addressfields on most entities, allowing users to add a location to most anything. Not just one country, but anywhere, since they could post photos from vacation etc. outside of the origin country that connects the private users. So having 1 country and hiding that 1 country is not applicable or helpful in achieving an addressfield that doesn't save an address when saved or edited and saved. Also, don't like the 2nd field having to be there, totally unnecessary if there is an "Add another" button, but that's another issue that's still not resolved.

I've tried several of the patches and they're either outdated with current versions or they overlap and alter the same lines which makes a non-module-coder like me unable to make it all work. Does anyone have any advice? Some of these issues have been going on for 2.5 years and I haven't really seen much feedback from the module maintainers to let us know if something is in the works or not. All effort is appreciated but all these issues are puzzling to try and get it working properly.

groovedork’s picture

I, too, am flabbergasted that I have found 4 threads around this issue, starting all the way back in 2011.

To me just setting the default to "don't save to the database if the user hasn't changed anything" would be preferable to always saving the country, which it does now. While not perfect, it seems like a more sane default.

__Use cases__
I can conceive more use-cases where people would fill in a complete address, than use cases where just the country alone would be valuable.

Situations where just the country alone would be logical to save:
- What is your favourite holiday destination? at a travel website
- Which national branch is this employee a part of? at a multinational firm

Situations where the entire address would be logical to save:
- User details (CRM, etc)
- Event location
- Location-based services/mapping

I recognise there are cases where just the country alone is a valid input. But I think most use-cases wouldn't concider just the country data to constitute an address.

mbrakken’s picture

A minor clarification: "- None - " is not in the dev branch. It's from #968112: Allow addressfield to be optional.

Given that there are 3 or 4 issues that deal with aspects of this issue and that none in my mind fully satisfy requirement, I feel we should try to pull together different threads and assess how they can interact with each other.

Unless I am mistaken, the goals of the different issues are as follows:

This thread (#1844846: Make Addressfield optional, (even if country is required) ) deals with content being saved in the database even if fields are empty. This means, too, that if a user does not touch the addressfield, they are defaulted as living in Afghanistan, since that's the first country value in the dropdown.

#968112: Allow addressfield to be optional adds a country value of " - none - " to the top of the list. It has some admin UI issues, leading to site builder uncertainty about how to configure it. Also, it still registers the field as populated, so values get saved. This means if you're using https://drupal.org/project/location_taxonomize with Addressfield like I am, you end up with a series of "Unknown" values attached to an entity.

#1263316: Configurable non-empty value conditions allows admin to define which elements of addressfield need to be have data in order to be determined complete and saved to the database. I think this addresses one of @groovdork's issues in #1844846-39: Make Addressfield optional, (even if country is required) . However, it has a UI problem in that it still has Afghanistan as the lead value, as opposed to " - none - " or just empty. It does have a check to see if default value was changed, but this isn't ideal in my opinion. An end user has no reason to think that a field showing Afghanistan is actually empty, and in my current tests where I have set country and city as both required, if I don't touch the address field on the form it still kicks an error at me telling me either to also add a city or to clear the country. There is no way to clear the country without some type of null value or reset function. I should note, though, that I applied the patch manually and so need to verify my code. (I'm learning PHP, and find it useful to manually manually patch in order to see how others structure their logics.)

I think the fourth issue referenced by @groovedork in #1844846-39: Make Addressfield optional, (even if country is required) might be #984788: Add "Remove" button to clear out values in a multi-value address field widget, which would as the title says, add a "Remove" button to a multivalue addressfield, in order to prevent populating excess empty addresses, or to eliminate existing ones. I haven't really looked at it since multivalue addressfields is not my use case, but thought I should include it.

I'm sure I missed some things, and have probably misinterpreted others, but I think the conversations across different issues need to be brought together so we don't work at cross purposes.

The main issue behind all this, that addressfield has problems with the concept of empty, is pretty huge as many others have noted. I'm going to try and assemble across the different issues above, because getting this right so that forms process as expected and users aren't confused or stuck is a leading concern for me. Let me know if I completely missed something that needs to go into this.

artusamak’s picture

If someone wants to test it, this issue is solved when using #1263316: Configurable non-empty value conditions - #66 and #970048: Define and use addressfield as a form element type - #79
The only point left will be the removal but should be handled in #984788: Add "Remove" button to clear out values in a multi-value address field widget as mbrakken efficiently summarized it.

klonos’s picture

@Artusamak: Thanx mate! Just a note to make your life easier. You can format direct links to issue comments like so: [#issue_id-comment_number]

It would make...

#1263316-66: Configurable non-empty value conditions: #1263316-66: Configurable non-empty value conditions
#970048-79: Define and use addressfield as a form element type: #970048-79: Define and use addressfield as a form element type

Try it next time ;)

klonos’s picture

Issue summary: View changes

Added some data about the used hook.

johnv’s picture

Issue summary: View changes
Status: Needs review » Needs work

ITMT, the current -dev version contains a hook_field_presave(), which we are also implementing in this issue.
So, we need to re-assess the patch.

jsibley’s picture

I am hoping that this is the best place to ask this question, as I am finding the multiple threads about optional addressfields somewhat confusing.

I believe that, if one is geocoding addressfield data, there needs to be a country. If true, then it makes sense for the country to be mandatory, even if the addressfield is optional.

If a user might have multiple addresses, the issue is made worse, as I believe that each time the user profile is saved, another address is saved and there is, as pointed out in other threads, no "remove" button yet for the additional fields.

So, for now, what is the best solution for multiple, optional addressfields with a mandatory country? I'm tempted to limit users to only one address until this gets straightened out, but that seems overly limiting for users that might have multiple addresses (I'm creating a user directory).

Are we at all close to a workable solution?

klonos’s picture

deanflory’s picture

Thanks klonos for the related link, looks like this may be a while...

klonos’s picture

I recently came across Field Suppress. I haven't actually used the module, so I don't know in what shape it is, but from its description:

Two new field settings are provided.
field_suppress: The following three states are provided.
never: Never suppress field data.
always: Always suppress field data. Any changes to field data will be ignored during entity update and insert.
load: Only suppress field data during entity_load() so any data added will be saved during entity update or insert.

field_suppress_blank: In some cases it may be useful to have a "blank" entry be added for a field that is suppressed. An example is when using this module with Field Group Views which uses field_group to replace the fields that are children of the group. If none of the fields have a value then the group will not be displayed. Keep in mind this is somewhat hackish since the field API does not provide a standard array structure so adding a "blank" row may not always work.

I'm not sure if or how, but the field_suppress_blank field setting seems that might prove useful if we used it for our cause.

PS: cross-posting this to the other related issues for those that don't follow here.

Naomi79’s picture

There is a patch here https://www.drupal.org/node/1263316#comment-8995979 that add new address field settings. Please see the screenshot attached.

Notes:
- Field Suppress module doesn't solve the issue because it does not apply to existing nodes.
- I tried to apply #37, #18, #12 with the patch manager module and got a fatal error "cannot redeclare function..." (back and front broken, if it happens to you: you just need to reinstall the address field module manually in sites/all/modules/addressfield to go back to normal).

bojanz’s picture

Status: Needs work » Closed (duplicate)

Addressfield has never been designed to be optional.
The "optional addressfield" issues have gathered over 200 comments with dozens of different approaches and use cases. Most wrong.
Therefore, it is not surprising that the issue has stayed unsolved for years.

I am going to close this issue as a duplicate of #968112: Allow addressfield to be optional, because that issue is the closest to a solution. I will post my proposal and patch there.

johnv’s picture

This is just to confirm that #49 is OK.

I am updating to version 1.0 and was using patch #17. Setting the default country to 'None' ( using the new functionality ) makes that no address field is stored when a country is not filled. If a default country is filled, the field is effectively required.

I do like the first feauture, do not care about the second feature.