Problem/Motivation
We should allow the Address widget (and form element) to support a list of preferred countries that would be grouped on top of the country selector.
This is important because sites frequently have the most visitors from a few countries. United States ends up being more important than Afghanistan, for example.
Proposed resolution
Add a widget setting to specify the list of preferred countries.
Also add support for a #preferred_countries array within the address form element.
Remaining tasks
Should the labels for the optgroups be configurable? Currently, they're translatable, but not configurable in the UI.Nah, we dropped the first opt-group label, and "Other" seems generic enough for everything else.Should the UI for selecting preferred countries in the form widget settings page honor the #available_countries list in the field settings?Fixed via patch #13.- We need to get the test for preferred_countries working
- Add validation for #preferred_countries: ensure it's an array, that if #available_countries is defined that everything in #preferred_countries is available, that the values are valid country codes, etc?
- Review + commit
User interface changes
A new 'Preferred countries' multi-select setting for the address field widget, and a corresponding change to the settings summary.
If a list of preferred countries is defined, the country select form element will use optgroups to have a 'Preferred' list at the top, and an 'Other' list for all the non-preferred countries.
API changes
Addition of a #preferred_countries array in the 'address' form element type.
Data model changes
Change to the widget settings configuration schema to hold the preferred_countries list.
Original report by bojanz
Preferred countries would be grouped on top of the country selector.
This is important because sites frequently have the most visitors from a few countries. United States ends up being more important than Afghanistan, for example.
| Comment | File | Size | Author |
|---|---|---|---|
| #60 | address-2626982-allow_set_list_countries-60.patch | 24.22 KB | phjou |
| #55 | preferred_countries-2626982-55.patch | 25.91 KB | tguerineau |
| #53 | preferred_countries-2626982-53.patch | 12.09 KB | tguerineau |
| #52 | preferred_countries-2626982-52.patch | 25.11 KB | sickness29 |
| #49 | preferred_countries-2626982-49.patch | 25.17 KB | sickness29 |
Issue fork address-2626982
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
goz commentedComment #3
goz commentedPull request is available on github : https://github.com/bojanz/address/pull/25
And patch is attached.
Comment #4
goz commentedAdd summary to preferred countries. This patch is in relation and dependance with #2633912.
Comment #5
goz commentedCompile commits. I only keep first patch related to #2633912.
Comment #6
meichr commentedI've used the patch of #5 on address-8.x-1.0-beta2 and it works. On the "Manage form view" settings page of the address field now also preferred countries can be selected. The default country and the preferred countries are now also displayed directly on the "Manage form view" which is a UX improvement I like.
There is one possible improvement I miss which would be a divider between preferred countries and the full list of the countries. The divider possibly should be managed in the field settings. What do you think?
Comment #7
bojanz commentedThe divider should always be present, no need to make it a setting.
Comment #8
meichr commentedRerolling the patch #5 to apply to current dev version and adapting content of method settingsSummary() due to introduction of this method since patch #5 in the unpatched module to avoid duplication by patch.
The devider has not yet been added to the select box.
Comment #9
pianomansam commentedPatch no longer applies to dev. It also doesn't include an update hook for existing address fields.
Comment #10
meichr commentedComment #11
dwwFor the divider, do we want to do this via:
A) option groups (e.g. making #options a nested array with 'Preferred' and 'Other' labels)
B) insert a bogus '-----' option that we disable
C) other
?
Thanks,
-Derek
Comment #12
dwwIn IRC, bojanz said:
So here's a re-roll that:
- Works with #2689089: Define a form element type "address" to support
#preferred_countriesin the 'address' form element.- Uses optgroup to separate preferred and other countries in the select list by defining #options as a nested array.
I began to port the changes to the automated test into tests/src/FunctionalJavascript/AddressDefaultWidgetTest.php. However, I couldn't get the new assertOptionOrder() method to work properly given the presence of optgroup tags. Frankly, none of the test assert methods related to select options that I tried seem to handle optgroup. :/ So, I just left those hunks of the patch out. If someone (especially if you're fluent in xpath hackery) wants to run with it, see 2626982-12.preferred_countries.broken-test.patch for my initial (failed) attempt.
Possible remaining todo items:
A) Should the labels for the optgroups be configurable? Currently, they're translatable, but not configurable in the UI.
B) Should the UI for selecting preferred countries in the form widget settings page honor the #available_countries list in the field settings?
C) Should we get the test for preferred_countries working again?
Re: @pianomansam in #9
What do we need an update hook for? We're not changing any existing field/widget settings. We're just adding support for a new one. I don't think we want to touch existing field configuration for this change at all. Or are you talking about adding an empty DB update to trigger a cache rebuild to ensure the field widget settings config schema changes take effect?
Thanks,
-Derek
Comment #13
dww- Converted this to a proper issue summary and added the remaining tasks section with the todo items from comment #12 (and a few others I thought of).
- Crossed off one of those items by removing todo 12.B. Both of the widget settings that let you select countries now honor the available_countries field setting.
However, I'm not entirely sure the change here is the right one. I'd rather reuse
AddressItem::getAvailableCountries()which has some caching and the whole AvailableCountriesEvent support. Sadly, I couldn't figure out how to access the underlying FieldItem from a given WidgetBase (at least not in settingsForm() -- some of the other methods have a list of items passed in).I suppose I could duplicate the code from src/Plugin/views/filter/CountryCode.php that does some unholy things to enable this to work:
$entity->get($field_name)->appendItem()->getAvailableCountries();, but that seems dirty and wrong. Maybe that's the best we can hope for. Seems pretty lame that the widget doesn't have a reference to the field anywhere. Maybe I'm missing something.Comment #14
bojanz commentedThis now needs a reroll for our address_country form element. The current code seems to be going in the right direction.
Comment #15
dwwRe-roll against latest 8.x-1.x and adds support directly in the address_country form element.
The TODOs from the summary are still basically valid. In particular, I'm wondering about making these labels configurable, and if so, how.
But this is getting closer. Reviews welcome.
Thanks,
-Derek
Comment #16
dwwAnd here's a version that adds support for this into the views CountryCode filter.
Comment #17
dwwAnd here's a version that applies cleanly to 8.x-1.3 after the patch from #2514126-102: Add field settings for global overrides of required/optional behavior is committed.
This can be used for sites that want both features now.
And once #2514126 hopefully this could go in soon thereafter without another re-roll.
Comment #19
dwwArgh, forgot to set the 'do not test' flag when I attached #17. Here's a re-upload of #16 so the bot doesn't get confused.
Comment #20
dwwAnd here's a pair of patches that let you configure the optgroup labels for the views country filter. Again, there's a version that applies cleanly with [ #2514126-102] applied.
Comment #21
dwwDo we want the field widget configuration to work roughly the same way for the optgroup labels in the form element? Or is there a cleaner/better way to let people configure this?
Thanks,
-Derek
Comment #22
dwwOr, *gasp* should the label config (and country list?) only live in the widget, then in the views filter code, we do something (potentially unholy) to pull the widget settings out of the field that the filter is pointing to, and re-use the same labels from the widget? This sounds dreadful to implement, but perhaps more what users would expect.
Then again, I can imagine situations where you want your field UI to have 1 list of common/preferred countries for data entry, while your views filters might want a different set for searching. Or whatever.
I thought it was safer (and way easier to implement) to keep the config totally separate between widget settings and views filter settings. But if bojanz will only commit this if the 2 are merged, I'm willing to try. ;)
Thoughts?
Thanks!
-Derek
Comment #23
panchoAn important UI improvement I definitly need for my current project (or any other address field deployment).
Here's just a straight reroll of #20 so it applies against latest dev.
Comment #24
dwwThanks for the re-roll, @Pancho! I had sort of forgotten about this issue. ;)
I tried to interdiff between #20 and #23 and my copy of interdiff couldn't handle it. ;) So I'm attaching a "raw" interdiff from this:
diff 2626982-20.preferred_countries.patch 2626982-23.preferred_countries.patch > 2626982.20_23.interdiff.txtI noticed we lost a minor (but IMHO useful) code comment, since
AddressDefaultWidget::formElement()is pulling different settings from different places and it seems helpful to alert readers to this fact.Unassigning, since I have no bandwidth to work on the rest of the remaining tasks right now.
Would love feedback from @bojanz about it, first.
Thanks,
-Derek
Comment #25
panchoThat’s because the old one doesn’t apply anymore which is why we needed a reroll in the first place.
However theoretically it should be possible to have an interdiff compare the old patch against the old version with the new patch against current dev. I’ve just not yet figured out how.
Thanks for readding the comment I missed. I’m gonna provide screenshots as soon as I get to it.
Comment #26
panchoI don't think we really need the "Preferred" optgroup at all. The preferred ones are at the top, it's obvious they're shortlisted, and everything else is visual clutter IMO.
Plus: The "Other" optgroup is fine as it is, and I don't think we need a configurable label for this one.
Here are some screenshots:
Before:

#24:

#26:

Further issues:
add all the same features to CountryItem;(fixed in #27); don't know about ZoneItemComment #27
panchoNext patch, adding the same feature for CountryItem (#26-2).
Does the amount of duplicated code justify an AddressWidgetBase class, a trait or some helper method?
Comment #28
panchoAnd of course we need formatPlural() for the settingsSummary.
That's it for the moment. Waiting for some feedback now, including on the remaining questions in #26 and #27.
All in all while #2838457: Re-enable the default value functionality for Address fields would be nice, too, I think this is even more helpful. On non-required fields, you often want the default country to be "none", so the other address fields don't pop up. The more is a shortlist of the most relevant countries a big plus in terms of usability.
Comment #29
panchoFixed another edge-case:
If all available countries are shortlisted, we don't want to show the "Other" optgroup either.
Comment #30
panchoComment #31
dwwRe: #26: Cool, good point that we don't need an optgroup label for the "preferred" list. Nice thinking!
Re: #26.1: Absolutely. "Preferred" is indeed judgmental, as you say. That's why I wanted to make the label configurable. However, "shortlisted" is a bit awkward. Some possible alternatives:
I don't love any of these, but I don't have a better suggestion (yet).
Agreed that "Other" is fine, without a config knob, for the (remaining) opt group.
Re: #26.3: yup, sounds good.
Thanks!
-Derek
Comment #32
bojanz commentedAgreed.
I chose "preferred" because Symfony uses that language:
https://symfony.com/doc/current/reference/forms/types/country.html
It can also be seen in random JS packages:
https://github.com/country-regions/country-region-selector
https://www.npmjs.com/package/react-telephone-input
Ruby on Rails calls it "Priority countries".
Magento calls it "Top destinations".
Django's main extension uses a COUNTRIES_FIRST setting.
Common countries seems a bit vague. I'd do either "Preferred countries" or "Top countries".
Comment #33
panchoI'm fine with "Preferred countries" as originally proposed by @GoZ. I'm fine with "Top countries," too. The wording is secondary, now that's it is no more user-facing.
Split #3034910: [PP-2] Automatically add the default country, if set, to the shortlist of "preferred countries" to a separate followup.
So we're only missing tests. Will add some, before I'm out for a week (on holidays).
Comment #34
panchoThe patch wasn't yet ready, as there were several glitches in the exposed filter form, in some of the various permutations of "required", "multiple", and "limit". I reimplemented the whole logic in a separate trait, so we're not unnecessarily duplicating this code.
From my manual testing, it seems to work now, but please give it another round of manual tests as well. We should then have a few functional tests as well as unit tests for the various permutations. Unfortunately, I'm out for a week, on holidays, so unassigning. If someone wants to step up and go ahead with the tests, feel free!
Comment #35
danielnv18Latest patch doesn't work in the latest commit (9cbec9f)
Comment #36
dwwIndeed. Doesn't even work with
patch -p1:@Pancho: Any chance you're setup to easily re-roll this for the latest 8.x-1.x branch? If so, I'd love to help get it finished and into Git ASAP.
Thanks!
-Derek
Comment #37
andreyjan commentedHere's the rerolled patch. There's no way to create an interdiff because the last patch is not applying.
Comment #38
ericawright commentedThanks for all your work on this! I needed similar functionality but for webforms, and found I had to tweak this slightly in order for it to work. I've included my patches here: https://www.drupal.org/project/webform/issues/3097456
I'm sure this isn't necessary for the first build of this feature (or at all), and there are definitely some tweaks that need to be made, but I thought I'd share in case anyone else was looking for the same thing.
Comment #39
chris matthews commentedComment #40
joe huggansThank you for this, working great with 8.x-1.8
Comment #41
lowfidelityThis plays well with address fields added to standard entity forms.
Can this feature somehow be used with Drupal commerce's Supported shipping countries and Supported billing countries widgets that are displayed to customers on the store's checkout page?
I would like to allow customers to choose from a wide range of countries, but show the most important countries at the top of the dropdown. I can't find any display settings for those two address fields.
Comment #42
sabina.h commentedTested the patch from #37 and it works great for me as well.
Comment #43
dieuweThis is just what I was looking for, great feature.
Comment #44
kthullLatest patch worked a treat. Would be great for this to get into a stable release.
Comment #45
junaidpvRe-rolled for current branch and release (8.x-1.11).
Comment #46
dinazaur commentedDuring the editing of the shipping method got the error
Had no time to investigate it. Here is a quick fix for the error.
Comment #47
dwwFabulous, thanks for moving this forward!
Unfortunately, I still can't commit this without tests (as tagged), which the latest patch does not contain.
Also, the summary has some remaining tasks
Comment #48
psf_ commentedWith patch in #46, If I use the field in a render array, then I get error:
Simple form code:
The error:
Comment #49
sickness29 commentedAdded 2 test cases for this: one for views exposed filter setting and the other for widget configuration and make sure selected countries are displayed as only options directly in select and not optgroup.
Also fixed code standards, added missing default values for Address and Country element info and fixed schema for views filter.
Comment #50
bojanz commentedThank you for the improvements, sickness29!
Since this is a major new feature and change in behavior, let's keep it limited to the 2.0.x branch. I'd like to keep the legacy 8.x-1.x branch as stress-free as possible.
Comment #51
dwwAgreed, this can be 2.0.x material at this point, since it's a potentially more "disruptive" new feature.
That said, I'm really excited about this, and will try to make time to review + test soon. Probably within the first week or two of December...
Thanks!
-Derek
Comment #52
sickness29 commentedReworked #49 to apply to 2.0.x
Comment #53
tguerineau commentedHi,
I've tested the
preferred_countries-2626982-52.patchpatch with the current 2.0.x branch and found that the patch doesn't apply due to code expected from the 8.x-1.x branch.After applying the rejected hunks manually and resolving duplications in
AddressDefaultWidget.php(mergedefaultSettings(),settingsForm()andsettingsSummary()methods), I've successfully tested manually the module with preferred countries field.The attached patch includes these modifications and works as expected. Please find my re-rolled patch attached for review.
Reworked #52 to apply to 2.0.x.
Comment #55
tguerineau commentedHello,
I am posting an updated version of the patch
preferred_countries-2626982-53.patch. This new patch addresses the issues encountered with the previous submission (preferred_countries-2626982-52.patch).Please find the attached re-rolled patch for review and testing. I welcome any feedback or further testing.
Reworked #52 to apply to 2.0.x.
Comment #56
dieuweThanks, this applies and runs well against the latest dev. Would be nice to get this committed after all these years.
Comment #57
bojanz commentedOur next release is 2.1.0, so let's change the version and start an MR.
EDIT: Pushed a few phpcs fixes, and the tests are mostly passing now. However, "phpunit (max PHP version)" is failing both in the MR and for the branch, we'll need to figure out why.
Comment #59
phjouIt seems like the pull request needs a rebase.
Comment #60
phjouJust posting an updated patch for the latest version of the module.
Comment #61
bojanz commentedUnassigning myself. Family and work obligations have left me with no time for Drupal contributions, so I will have to restrict myself to bug fixes. One of the other maintainers can pick this up when convenient.
Comment #62
interdruper commented#60 works like a charm in 2.0.4 release. Thanks.
Comment #63
anybodyThis would still be super helpful and is RTBC.