Right now people need to click "Recalculate shipping" at checkout when they change the address, to refresh the form.
That should be done automatically like in 1.x.

1) Hide the button.
This should do the trick:

  '#attributes' => [
      'class' => ['js-hide'],
  ],

2) When the address changes (no clue which JS event to use, check 1.x), check that the address is complete, and if it is, click the button.

Notes;
1) The address is complete if all of its required fields are filled.
2) Once the field is complete, we only need to recalculate if one of these fields changed: dependent_locality, locality, postal_code, administrative_area.
We don't care about the name, organization, address lines.

CommentFileSizeAuthor
#186 without-patch.png34.77 KBintrofini
#186 with-patch.png35.11 KBintrofini
#185 2849756-185.patch228.79 KBjsacksick
#184 2849756-184.patch228.9 KBjsacksick
#178 interdiff-177-178.txt6.9 KBpivica
#178 2849756-178.patch26.24 KBpivica
#177 interdiff_176_177.txt1.09 KBkhiminrm
#177 2849756-177.patch25.65 KBkhiminrm
#176 interdiff_173_176.txt476 byteskhiminrm
#176 2849756-176.patch24.44 KBkhiminrm
#173 interdiff_171_173.txt1023 byteskhiminrm
#173 2849756-173.patch24.41 KBkhiminrm
#171 interdiff_170_171.patch1.68 KBkhiminrm
#171 2849756-171.patch25.67 KBkhiminrm
#170 interdiff_169_170.txt4.09 KBkhiminrm
#170 2849756-170.patch25.48 KBkhiminrm
#169 interdiff_165_169.txt4.45 KBkhiminrm
#169 2849756-169.patch24.82 KBkhiminrm
#167 interdiff_165_166.txt4.45 KBkhiminrm
#165 interdiff_164_165.txt13.95 KBkhiminrm
#165 2849756-165.patch24.19 KBkhiminrm
#164 interdiff_163_164.txt2.64 KBkhiminrm
#164 2849756-164.patch16.24 KBkhiminrm
#163 interdiff_162_163.txt3.78 KBkhiminrm
#163 2849756-163.patch13.97 KBkhiminrm
#162 interdiff_157_162.txt2.78 KBkhiminrm
#162 2849756-162.patch9.94 KBkhiminrm
#159 autorecalculate_off.gif1.93 MBshabana.navas
#159 changing_states.gif2.04 MBshabana.navas
#158 illegal_choice_detected.gif2.75 MBshabana.navas
#157 shipping_autocalculate_reroll.patch9.31 KBau_dave
#156 2849756-156.patch972 bytesBogdan Nedelcu
#148 2849756-145-148-interdiff.txt1.09 KBflocondetoile
#148 2849756-148.patch24.81 KBflocondetoile
#145 2849756-145-138-interdiff.txt9.59 KBmbovan
#145 2849756-145.patch24.45 KBmbovan
#138 2849756-135-138-interdiff.txt12.93 KBflocondetoile
#138 2849756-138.patch27.85 KBflocondetoile
#135 2849756-135.patch16.65 KBflocondetoile
#133 2849756-133.patch16.48 KBflocondetoile
#133 2849756-interdiff-130-133.txt685 bytesflocondetoile
#130 2849756-130-126-interdiff.txt751 bytessasanikolic
#130 2849756-130.patch16.29 KBsasanikolic
#126 2849756-126-117-interdiff.txt5.18 KBmbovan
#126 2849756-126.patch16.29 KBmbovan
#124 2849756-updated-to-latest-dev-20200101-3.patch16.45 KBfinex
#123 2849756-updated-to-latest-dev-20200101-2.patch16.45 KBfinex
#122 2849756-updated-to-latest-dev-20200101.patch15.79 KBfinex
#120 2849756-updated-to-latest-dev.patch16.42 KBfinex
#117 2849756-117.patch19.45 KBberdir
#112 2849756-112.patch19.17 KBlisastreeter
#111 2849756-111.patch18.38 KBlisastreeter
#110 2849756-110.patch18.08 KBlisastreeter
#109 2849756-109.patch14.55 KBlisastreeter
#108 2849756-108.patch14.21 KBlisastreeter
#107 2849756-107.patch13.83 KBlisastreeter
#99 2849756-99.patch11.73 KBmglaman
#98 2849756-98.patch12 KBmglaman
#93 2849756-93.patch11.91 KBluksak
#92 2849756-91.patch12.22 KBluksak
#83 2849756-83.patch12.18 KBheddn
#83 interdiff_82-83.txt1.5 KBheddn
#82 commerce_shipping-auto-recalculate-shipping-when-address-changes-2849756-81.patch12.01 KBluksak
#74 interdiff_65-69.txt7.09 KBheddn
#74 interdiff_64-65.txt2.46 KBheddn
#74 interdiff_62-64.txt735 bytesheddn
#74 interdiff_61-62.txt15.77 KBheddn
#69 commerce_shipping-auto-recalculate-shipping_28949756-69.patch12.5 KBrwanth
#65 interdiff-64-65.txt2.61 KBjsacksick
#65 commerce_shipping-auto-recalculate-shipping-when-address-changes-2849756-65.patch8.89 KBjsacksick
#64 commerce_shipping-auto-recalculate-shipping-when-address-changes-2849756-64.patch9.52 KBjsacksick
#64 interdiff_-62-64.txt825 bytesjsacksick
#62 commerce_shipping-auto-recalculate-shipping-when-address-changes-2849756-62.patch8.98 KBjsacksick
#61 2849756-61.patch9.95 KBfastangel
#59 2849756-59.patch9.83 KBheddn
#59 interdiff_55-59.txt2.11 KBheddn
#58 interdiff_55-56.txt1.1 KBsavel
#58 autorecalculate_shipping-2849756-56.patch11.64 KBsavel
#55 interdiff_49-55.txt633 bytesheddn
#55 2849756-55.patch11.43 KBheddn
#49 2849756-49.patch11.38 KBharings_rob
#47 interdiff.txt2.45 KBharings_rob
#47 2849756-47.patch6.02 KBharings_rob
#45 commerce_shipping-autorecalculate-2849756-45.patch10.4 KBluksak
#35 commerce_shipping-autorecalculate-2849756-35.patch7.69 KBransomweaver
#32 commerce_shipping-autorecalculate-2849756-32.patch7.69 KBjsacksick
#29 commerce_shipping-autorecalculate-2849756-29.patch6.43 KBreplicaobscura
#26 commerce_shipping-autorecalculate-2849756-26.patch6.29 KBreplicaobscura
#26 interdiff-2849756-21-26.txt823 bytesreplicaobscura
#21 interdiff-2849756-10-21.txt8.78 KBreplicaobscura
#21 commerce_shipping-autorecalculate-2849756-21.patch6.11 KBreplicaobscura
#19 commerce_shipping-autorecalculate-2849756-19.patch6.24 KBreplicaobscura
#18 interdiff-2849756-10-15.txt8.62 KBreplicaobscura
#15 commerce_shipping-autorecalculate-2849756-15.patch6.29 KBreplicaobscura
#13 commerce_shipping-autorecalculate-2849756-13.patch5.75 KBreplicaobscura
#10 autorecalculate_shipping_2849756-10.patch6.06 KBransomweaver
#7 autorecalculate_shipping_2849756-7.patch8.01 KBransomweaver
#5 autorecalculate_shipping_2849756-5.patch5.06 KBransomweaver
#4 autorecalculate_shipping_2849756-4.patch4.74 KBransomweaver
#2 autorecalculate_shipping_2849756-2.patch4.65 KBransomweaver

Comments

bojanz created an issue. See original summary.

ransomweaver’s picture

StatusFileSize
new4.65 KB

Patch for autorecalculation, derived from the 7x javascript. there is a commented out section of js/shipping_checkout.js relating to "If other ajax logic is still running" that I was unsure if its still needed or how to apply it.

ransomweaver’s picture

Note that it might be a good idea to make the review button unclickable until the initial ajax shipping recalc has happened. See this issue for what can happen if the user manages to click to review before shipping is calculated: https://www.drupal.org/node/2849594

ransomweaver’s picture

StatusFileSize
new4.74 KB

This patch disables the continue button until shipping is calculated. It also changes to do start a recalc if the family or given name is changed, as I found that before when it was not attaching change to those, if you skipped over those required profile fields and filled all the address fields, the form would show those fields as needing filling and not ajax load the shipping methods, and then when you filled the names it wouldn't trigger the calculation.

This patch also includes the fix to the recalculate button removing #limit_validation_errors so that the billing profile form isn't sent empty when using an existing payment method.

bojanz sez this should get no-js treatment with php validation but I say he's craaazy. I'll make another issue for that.

ransomweaver’s picture

StatusFileSize
new5.06 KB

Oops, I left out the libaries.yml from the last patch.

ransomweaver’s picture

I think this needs a bit of work because

a) the recalculate can trigger the enabling of the review button too soon (allowing user click before its ready in the form?)
b) testers have complained about having to leave focus of the address fields (e.g. the last zip field) before it recalculates, leaving them waiting.

ransomweaver’s picture

StatusFileSize
new8.01 KB

Here's an updated patch which won't enable the review button until the shipping method has loaded, and also will trigger recalculation after 1.5 secs of user inactivity after changing a shipping profile field.

As a bonus I have added in javascript a "Shipping same as Billing" behavior with a checkbox to copy field values from the billing profile fields to the shipping profile fields. the checkbox is hidden if there are no billing profile fields (e.g. if the customer changes to use an existing payment method).

I also added support for triggering recalculation if there is a reusable shipping profile selected, as in https://www.drupal.org/node/2844920.

bojanz’s picture

Status: Active » Needs work

According to https://www.drupal.org/docs/develop/standards/javascript/javascript-codi... the JS code should be indented with 2 spaces, not 4.

As a bonus I have added in javascript a "Shipping same as Billing" behavior with a checkbox to copy field values from the billing profile fields to the shipping profile fields. the checkbox is hidden if there are no billing profile fields (e.g. if the customer changes to use an existing payment method).

We can't commit that for several reasons:

1) Shipping information comes before Payment information at checkout, so it's the Payment information billing profile form that needs a "same as shipping" checkbox.
2) The checkbox needs to result in the same profile ID used by both parent entities, instead of just copying the data.

+            // validate minimum fields to calculate shipping
+            var street = $('[id^="edit-shipping-information-"] .form-item .address-line1').val();
+            var locality = $('[id^="edit-shipping-information-"] .form-item .locality').val();
+            var admArea = $('[id^="edit-shipping-information-"] .form-item .administrative-area').val();
+            var postal = $('[id^="edit-shipping-information-"] .form-item .postal-code').val();
+            if (street && locality && admArea && postal && postal.length > 4) {
+                recalculate = true;
+            }

We should not be looking at address line 1.
Our relevant fields are: dependent locality, locality, administrative area, postal code BUT only if each one is actually present on the form and required.
We can further optimize dependent locality / locality / administrative area by only caring about them if they're select boxes (meaning that they are predefined and can have conditions against them). Note that we want the mentioned fields to trigger a recalc on change even if they're not required (as long as they're present and selects).

gaurav.kapoor’s picture

error: patch failed: src/Plugin/Commerce/CheckoutPane/ShippingInformation.php:207
error: src/Plugin/Commerce/CheckoutPane/ShippingInformation.php: patch does not apply

Getting this when trying to apply patch.

ransomweaver’s picture

StatusFileSize
new6.06 KB

Rerolled patch against latest dev incorporating Bojanz's review:
- 2 space tab
- remove shipping same as billing
- not require address1
- trigger on dependent locality / locality / administrative area only if required and are filled
- input to ANY field (except country) triggers CHECK to see if basic requirements to recalulate are met.

gaurav.kapoor’s picture

Status: Needs work » Needs review
chishah92’s picture

This patch works fine, but there is one issue. On loading the checkout page, the shipping amount should also be updated as line item in order summery. We are getting the updated cost in review.

replicaobscura’s picture

I did just a little bit of refactoring of the .js file in the last patch. It wasn't applying to my address elements properly and was running immediately causing validation errors to show up right away. This may or may not be due to me using a different patch for the profile select widget. I think this version of the patch should still work without the profile select patch, however.

The only issue I still do have is that often multiple requests are fired at once. I think that multiple events in the JS might be firing, causing two or more subsequent requests to get queued up, and this seems to be causing remote shipping calculation via FedEx to fail in some cases for me (but I haven't figured out why yet, may not be related to this patch).

replicaobscura’s picture

I'm working on some additional fixes for the issue I'm having that's causing it to run multiple times (and getting rid of the console.log lines I accidentally left in my previous patch).

replicaobscura’s picture

StatusFileSize
new6.29 KB

Here's a better patch, I think.

It limits the events that are fired to try and avoid duplicate events firing. Additionally, it adds a cache of sorts of previously submitted values and only fires a new request of one of the submitted values is changing. This code may need some tweaking, but it definitely reduces the number of times it needs to run on my site.

gaurav.kapoor’s picture

bojanz’s picture

@bmcclure
Can you please post an interdiff?

replicaobscura’s picture

StatusFileSize
new8.62 KB

First interdiff, let me know if I've done anything wrong here creating it. Thanks!

replicaobscura’s picture

StatusFileSize
new6.24 KB

Here's a quick update that makes it work when not using the patch for the profile select widget, too. Only one minor change to a conditional so I didn't re-do the interdiff, but I can if desired.

replicaobscura’s picture

I've noticed that it'd be useful if the JS also took into account other required profile fields outside of the address to block it from attempting to calculate. I have a field_phone field that's required, and using this patch the calculation is attempted and the form reloaded with validation errors before I've had a chance to fill out the field yet. I'll likely have an updated version of the last patch posted shortly.

replicaobscura’s picture

StatusFileSize
new6.11 KB
new8.78 KB

New patch (and interdiff against #10) with a slightly different approach to validating the shipping fields in the JS.

Rather than assume which fields to validate, this abstracts the selection of the required profile fields to a separate function used in several places. I think this is a bit more consistent and maintainable, and it now means that all required profile fields must be filled out for shipping to calculate.

googletorp’s picture

Status: Needs review » Needs work

A few thoughts:

We should make it configurable if you want automatic recalculation on address change or not. While it certain will be common for shops to have different prices based on the destination, not all shops work like this.

I'm not sure if best behavior is to hide the recalculation button or not. Since any factor can change the prices (we really don't know how the shipping logic will work), maybe we should default to showing the button and let each shop handling the styling of it. They can in the theme decide to hide it if need be.

I'm not sure if using data-drupal-selector is a good way for targeting. While it "works", I don't think it's a reliable selector to use, can't we do any better?

Also remember comments need to be on their own line, they should never be at the end of a line containing code.

bojanz’s picture

We should make it configurable if you want automatic recalculation on address change or not. While it certain will be common for shops to have different prices based on the destination, not all shops work like this.

Sure, why not. We should default it to "on", though.

I'm not sure if best behavior is to hide the recalculation button or not. Since any factor can change the prices (we really don't know how the shipping logic will work), maybe we should default to showing the button and let each shop handling the styling of it. They can in the theme decide to hide it if need be.

I'm fine with hiding the "Recalculate shipping" button cause that's what 7.x-2.x does. If people raise the issue we can rethink it, but for now it certainly seems like the majority use case. Plus, this hiding would only occur if address recalculation is on.

googletorp’s picture

@bojanz Makes sense, so to recap:

- Auto recalculation should be configurable.
- Default is to have it enabled.
- Hide button if enabled.

chishah92’s picture

The patch doesn't work well if i apply patch for profile reselect https://www.drupal.org/node/2844920

Issues faced :
1) On edit, if i click on the edit button in the order information page and change only name field, the continue to review button remains disabled. It only gets enabled on change event of locality.

replicaobscura’s picture

StatusFileSize
new823 bytes
new6.29 KB

Here's a really minor update to my last patch that resolves the issue of the Continue button getting disabled in some cases for me.

chishah92’s picture

@bmcclure : This patch does not work if the user places the order for the first time, adds the shipping address and then clicks on billing address same as shipping address checkbox

Note: This is when i apply patch from https://www.drupal.org/node/2852207

replicaobscura’s picture

I've got some fixes to this patch I've been testing, I'll post an update today. Also got a new patch for the other issue in the works, and I'm using them all together now so hopefully that will solve your issue as well.

replicaobscura’s picture

Status: Needs work » Needs review
StatusFileSize
new6.43 KB

Here's a new patch to try. It could still uses tests, and may need some additional functionality, but I'd like to get people trying it to see if it works for them too.

The only real issue I'm experiencing, is that if you stop typing in a field for 1.5 seconds and then start again, whatever you continue typing is lost when the AJAX returns. Perhaps there's a way we can cancel the AJAX request so it doesn't replace the form if you start typing again before it completes?

chishah92’s picture

Now, this patch is working fine even after applying patch for shipping address same as billing address. However i am trying to reproduce the ajax issue i.e trying to stop typing in a field for 1.5 seconds, but cannot reproduce it in my case.

replicaobscura’s picture

If you start typing at the same time that the AJAX request is fired off, then when the AJAX request returns any characters you entered while the request was running are removed, since the whole profile form is replaced with a copy of the input that was present when the AJAX request was submitted.

I'm able to reproduce it on a clean install, though the AJAX request happens quicker there so it's less noticeable than on my large site. I haven't looked into it yet, but I'm wondering if we can use an AJAX event listener or something to cancel the returned event if more text has been entered already, since that means another request will fire shortly anyway.

jsacksick’s picture

I can think of two solutions in order to fix the problem described:
1) Refresh only the "shipments" portion of the ShippingInformation pane.
2) Disable the fields during the Ajax request so that no information are lost during the ajax refresh...

I implemented the option 1 and I wasn't able to reproduce the issue described this way.

@bmclure: could you test the attached patch?

replicaobscura’s picture

Sure, I'll get this tested ASAP and report back. Thanks!

frank hh-germany’s picture

Hi, i have implement the Patch and my site runs without errormasages. Ok, fine.

But how it works and how can i use this?

My Goal, same as in DC7, recalculate Shippingcost by Country and/or Postal Zipcode.

I think we need on
admin/commerce/config/shipping-methods/manage/
Checkboxes, called Shippingcostcalculation by, or Show Shippingcosts only for,
Zip Code (with field for entering Zip codes)
Country (with field for entering Countrys)

And a field for set negate (true, fals)

ransomweaver’s picture

StatusFileSize
new7.69 KB

With the arrival of D8.4 and jQuery 3, $(window).load() doesn't work anymore. Attached patch fixes to use .on('load'

luksak’s picture

Status: Needs review » Needs work

Something isn't working for me with this patch. hook_commerce_shipping_methods_alter() is being called, but the shipping methods available dont change the first time. Chinging the shipping country again throws errors:

Illegal choice 1--default in Shipping method element.
and
Error: Call to a member function getPlugin() on null in Drupal\commerce_shipping\Plugin\Field\FieldWidget\ShippingRateWidget->extractFormValues() (line 160 of /var/www/drupal/public_html/web/modules/contrib/commerce_shipping/src/Plugin/Field/FieldWidget/ShippingRateWidget.php) #0 /var/www/drupal/public_html/web/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php(222): Drupal\commerce_shipping\Plugin\Field\FieldWidget\ShippingRateWidget->extractFormValues(Object(Drupal\Core\Field\EntityReferenceFieldItemList), Array, Object(Drupal\Core\Form\FormState))

luksak’s picture

To clarify: this was thisting using commerce_shipping 2.0-beta4. When using the regular "Recalculate shipping" button without this patch the right shipping methods are displayed.

ransomweaver’s picture

Status: Needs work » Needs review

at 2.0 I don't get any error if I do this:

/**
 * Implements hook_commerce_shipping_methods_alter().
 */
function mymodule_commerce_shipping_methods_alter(&$shipping_methods, $shipment) {
  // Only offer the shipping method with the ID '1' for orders over $100.
  $amount = new \Drupal\commerce_price\Price('100', 'USD');
  /** @var \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment */
  if ($shipment->getOrder()->getTotalPrice()->lessThan($amount)) {
    // '1' is the ID of the shipping method that we're removing.
    unset($shipping_methods[1]);
  }
}

It correctly removes shipping method 1.

I don't know if anyone has ever tested any of these patches with beta4. beta5 was released Dec 26 2016, and this issue was created Feb 17 2017.

It doesn't seem reasonable for this to be made backwards compatible to the betas at this point. @Lucas von Blarer you should probably make your own version of the patch if you can't update from betas for some reason.

luksak’s picture

Status: Needs review » Needs work

Beta4 is the current release and was released yesterday. I did try the patch on beta3 without success.

Is it working for you on the latest releases fo commerce and commerce_shipping?

ransomweaver’s picture

@lukas sorry, I was thinking of commerce beta4. Yes, its working on the latest commerce and dev commerce_shipping for me.

luksak’s picture

Ok... Could you tell me how to debug this? I have some troubles understanding the code in shipping_checkout.js...

ransomweaver’s picture

@lukas How the shipping_checkout.js works: For starters, there should be no shipping methods displayed with an empty shipping info form. Then when sufficient fields are filled, it triggers mousedown on the (hidden) shipping recalculation button. After the ajax call completes, the shipping methods are displayed. If all this happens for as described, then I don't think there is any bug in this patch at all, because this patch has nothing to do with what data is returned by the ajax request for shipping methods, and has nothing to do with changing shipping methods after changing the selected country.

As for logging/debugging php code that is executing in an ajax call, I like to use object_log module.

luksak’s picture

The shipping methods are displayed from the beginning and the don't change. might it be an issue with selectors within the JS?

luksak’s picture

1) Ok, I found the issue. In my hook_commerce_shipping_methods_alter() I use $shipment->getShippingProfile()->get('address') and disable shipping methods according to the country code. Since the shipping profile hasn't been saved yet, it isn't available yet.

I worked around this by using the values from the request if set:

<?php
$shipping_information_request = \Drupal::request()->request->get('shipping_information');
$country_code = $shipping_information_request['shipping_profile']['address'][0]['address']['country_code'];
?>

But this is not a nice solution...

I found the following other issues with the patch:

2) There are postal codes shorter than five characters. The Faroe Islands for example have only three digits. How can we find out what the minimum length for the selected country is? The size attribute on the input is always 10...

recalculate = ($postalCode.val().length && $postalCode.val().length > 4);

3) If the user enters a shipping address, selects a shipping rate, then enters a new address which makes the selected shipping rate unavailable, I get this error:

Error: Call to a member function getPlugin() on null in Drupal\commerce_shipping\Plugin\Field\FieldWidget\ShippingRateWidget-&gt;extractFormValues() (line 160 of /var/www/drupal/public_html/web/modules/contrib/commerce_shipping/src/Plugin/Field/FieldWidget/ShippingRateWidget.php).

luksak’s picture

The attached patch addresses 2) and 3) in #44 using workarounds:

2) reduced the minumim length to 1 character. This will cause invalid postal code messages but at least shipping rates are being refreshed.

3) there is a check if the shipping method is still available in the new widget. If fixes the error, but results in a An illegal choice has been detected. Please contact the site administrator. message.

shadeworm’s picture

Is it possible to place shipping option on the next page after shipping address input so that there are less difficulties that need to be overcomed?

harings_rob’s picture

StatusFileSize
new6.02 KB
new2.45 KB

I found that, when you change the country after you already received the calculated shipping, an error occurred similar to this:
https://drupal.stackexchange.com/questions/250078/ajax-submission-leads-...

By changing the ajax response this issue was resolved.

Attached the interdiff and new patch.

fotograafinge’s picture

#45 the shippingcosts are not always recalculated (at least not for anonymous users, for users with an account no problem). Only the 'pickup' cost is shown (no calculation needed, available for alle orders), not the calculated shipping based on country and torder total.

#47 the shippingcost does not appear when I enter the address. FYI: My shippingcostst are hidden until an address is entered. But they don't show with this patch.
Even when shippingcosts are not hidden untill calculated, the calculated shippingcost does not appear.

harings_rob’s picture

StatusFileSize
new11.38 KB

My latest patch was missing the javascript files. That is why there was no calculation at all.

fotograafinge’s picture

Thx @harings_rob. Now it shows, but still the same problem as with the patch from #45. For anonymous users, the shippingcosts are not calculated.

For logged in users with a profile, there is no problem. When they switch country, the shippingcosts are recalculated just fine.

fotograafinge’s picture

I tested it some more. There is only an issue for anonymous user. Their shippingcosts aren't recalculated. Seems like the calculation does not get the country.
(even with the "Recalculate shipping" button it's an issue so maybe I need to make a new issue for this ?)

heddn’s picture

Status: Needs work » Needs review

Way back in #39 this was put into NW. But it seems that some folks are still using this with some success. Let's see what happens when change status again.

heddn’s picture

Status: Needs review » Reviewed & tested by the community

I'm using a hacked copy of the patch from #49 with profile_select enhancements in #2948954: Commerce_profile_select reusable profiles. It is only hacked so it will apply. The code is the same.

The only thing I could see improving this is around the 1.5 seconds before auto-submitting. That seems like a long time. But otherwise, this worked quite nicely. I'm not going to hold up this fine specimen of work on half a second. Onward and upward.

savel’s picture

It's worth to mention patch from #49 (and maybe earlier) requires PHP 7.1 and higher.

The reason for this is using PRIVATE modifier for const:

 /**
  * The shipping options wrapper.
  */
 private const SHIPPING_OPTIONS_WRAPPER = 'shipping-information-shipments-wrapper';
heddn’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new11.43 KB
new633 bytes

Status: Needs review » Needs work

The last submitted patch, 55: 2849756-55.patch, failed testing. View results

savel’s picture

#55 Tests are failed because of hidden "Recalculate shipment" button.

The way to make it pass is to make new feature disabled by default (enabled with switch in admin backend).

The real problem with this PATCH: it silently breaks/changes pane validation process. After patching I don't see inline validation errors for the Shipping pane.

AFTER doing a littile research (and reading all the posts in this thread):
I've realised that validation process was changed in #32 and #47 and even earlier.

With #55 recalculation don't fire if any of the required fields are empty. Without any message. This can cause a problem in scenario:
1) All fields are filled and shipments are calculated/displayed/selected.
2) Then empty any required field.
3) Change address to other, with different shipping methods available => nothing happens. Shipping methods are displayed for previous location without any message.

savel’s picture

StatusFileSize
new11.64 KB
new1.1 KB

I've changed the validation for required fields on client-side.

Instead of doing nothing when there are any unfilled fields found, it puts a message in a shipments selector area (also hides any previous results).

heddn’s picture

StatusFileSize
new2.11 KB
new9.83 KB

This goes back and re-introduces the issue identified in #29. But is also validates the address again, which is more important than losing a couple letters from a stuttery typer.

Incremental improvements.

fastangel’s picture

This patch doesn't work with the last version of the module. I'm working for reroll.

fastangel’s picture

StatusFileSize
new9.95 KB

Here the patch updated.

jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new8.98 KB

I've been working on this today, and wrote a new patch which is heavily inspired from the D7 version.
The tests had to be updated because the "Recalculate shipping" button is now hidden.
It seems to work as expected based on my several tests.
However right after updating the state, if the zipcode is already filled as well as all the required fields, the recalculate shipping button is automatically clicked but the zipcode is now wrong, which leads to a validation error.

IMO that's a minor issue that can be fixed later, or we can empty the zipcode once the state is updated...

Status: Needs review » Needs work

The last submitted patch, 62: commerce_shipping-auto-recalculate-shipping-when-address-changes-2849756-62.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new825 bytes
new9.52 KB
jsacksick’s picture

Ok, so I just tested the patch on the Belgrade theme and it was failing for 2 reasons:
Our method for detecting that there's an ajax request occuring is failing (because there's an element that has the "ajax-progress" class.

  1. That logic is probably unnecessary at this point because it was there in d7 to prevent a failure when the profile copy checkbox was checked.
  2. The selector for the "Recalculate shipping" button on Bootstrap is wrong, cause Bootstrap uses "button" instead of inputs.

So the attached patch is getting rid of the logic for detecting that there's an ajax request (we can still put it back later once the need arises) and fixes the selector.

gmem’s picture

Status: Needs review » Reviewed & tested by the community

Reviewed this both with the stock Drupal theme and the Drupal Orange theme and this appears to work as described. As #62 mentioned the zip code does fail validation if the province/state is changed when it's filled in, but maybe this should be billed as a feature instead, since it let's the customer know it's not right instead of silently failing. Tests also all pass for me.

The last submitted patch, 59: 2849756-59.patch, failed testing. View results

rwanth’s picture

Status: Reviewed & tested by the community » Needs work

Based on my testing, the changes between patch 64 and 65 created an error. When "Hide shipping costs" is true, the patch does not render the shipping methods at all. In order to proceed, a user has to try to continue to the next step of checkout (and get an error message.) Leaving the 'ajax-progress' in place seems to resolve this issue.

rwanth’s picture

The attached patch includes functionality added in patches #63-5 while reverting the javascript to patch #61 so that the ajax calls are functioning.

jsacksick’s picture

@rwanth: Some changes introduced in #65 are required to make it work on Bootstrap based themes.

Also, it seems like the tests aren't passing anymore.

Could you give me steps in order to replicate the issue you described in #68?

rwanth’s picture

@jsacksick thanks for the quick reply.

In Checkout Flow: enable both auto-recalculate and hide shipping costs in the shipping information pane
Proceed to checkout (tested as anonymous, authenticated and administrator)
Enter all required fields in shipping form
Expected behavior: available shipping methods should render underneath shipping form with default radio selected
Shipping methods do not render
Fill out all available fields and attempt to proceed to next step of checkout
Page refreshes and receive error "Please select a shipping method"
Shipping methods displayed and can continue with checkout

This is the case for me on both #64 and #65 using a Bootstrap-based theme.

Upon further testing, my patch #69 has the same error when logged in as an administrator; however, it works as expected for anon and auth users.

luksak’s picture

This patch needs a re-roll.

Was a composer issue. The patch still applies.

jsacksick’s picture

Status: Needs work » Needs review

@rwanth: I just tried with several themes again (Belgrade, Bootstrap, Commerce Bootstrap as well as the default "Bartik" theme, and it works for all of them (I can't reproduce the issue you're describing).

Additionally, the tests are failing with the patch you submitted in #69 and the JS code seems unnecessarily complex.

@Lukas von Blarer: is the patch working for you? Which one did you test?

heddn’s picture

StatusFileSize
new15.77 KB
new735 bytes
new2.46 KB
new7.09 KB

There have been lots of patches recently without any interdiffs. Let's add some.

heddn’s picture

#65 nor #69 work on my site. I'm combining it with some other things on the shipping info pane, so I'll have to dig through what is the conflict or if it is an underlying problem with one of those two patches.

heddn’s picture

I'm thinking it might be interactions w/ #2844920: Allow customer profiles to be reused.

bojanz’s picture

@heddn
This patch definitely doesn't support profile select. That will be a followup for when profile_select lands.

luksak’s picture

I can't get the current version of the patch working since #2898137: Replace hook_commerce_shipping_methods_alter() with a FilterShippingMethodsEvent got in. I converted my hook altering shipping methods to a event subscriber that chooses the shipping methods based on address, weight, etc. If my event subscriber removes a shipping method that was selected before, I get the error described in #36 again:

Error: Call to a member function getPlugin() on null in Drupal\commerce_shipping\Plugin\Field\FieldWidget\ShippingRateWidget->extractFormValues() (line 153 of /var/www/drupal/public_html/web/modules/contrib/commerce_shipping/src/Plugin/Field/FieldWidget/ShippingRateWidget.php)

Actually this is also the case without this patch when hitting the "Reculaculate shipping" button. Should we create a new issue for that?

luksak’s picture

Status: Needs review » Needs work

I realized that the patch in #65 removed the check I added in my patch in #45. Is there a reason this has been removed?

luksak’s picture

It was removed in #62. I'll upload a patch based on #65 with that check later today...

heddn’s picture

+++ b/js/shipping_checkout.js
@@ -0,0 +1,51 @@
+        $(window).once('commerce-shipping').on('load', function () {

Re #76/#77: I had some time to think about this over the weekend. I think the reason it isn't working is because we bind once to the DOM. But with reused profiles, we have AJAX replacing the dom. So we shouldn't use once. Or re-add MutationObserver. Or something.

luksak’s picture

Status: Needs work » Needs review
StatusFileSize
new12.01 KB

Here it is.

heddn’s picture

StatusFileSize
new1.5 KB
new12.18 KB

So, this makes it work with #2844920: Allow customer profiles to be reused. Sorta. I still face an issue if someone enters an invalid postal code, the shipping rate is re-calculated and there's no recovery. But I think that was an issue with or without this patch.

finex’s picture

Hi, thanks for the patch. It works fine.

Would be possible to keep the shipping rate updated on the Cart Summary in the sidebar (checkout page) and on the Cart page either?

p4trizio’s picture

Status: Needs review » Reviewed & tested by the community

Fantastic! #83 works great thanks.
Setting the status to RTBC unless other things come up

xpersonas’s picture

Patch in #83 is working well for me so far.

cameron prince’s picture

finex’s picture

Hi, now that https://www.drupal.org/node/2710999 has been solved, would be possible to refresh the cart summary with the selected shipping rate?

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 83: 2849756-83.patch, failed testing. View results

luksak’s picture

With one of the recent releases of commerce, the patch stopped working for me.

luksak’s picture

Status: Needs work » Needs review

This is a patch for beta5 since I got stuck on that one.

I have one additional field an the customer profile storing their phone numbers. This caused the shipping methods to never refresh. I changed the selector in shipping_checkout.js to only include fields inside .field--type-address. I have no idea if this is a viable approach, but works for me so far.

luksak’s picture

StatusFileSize
new12.22 KB

And here is the patch :)

luksak’s picture

StatusFileSize
new11.91 KB

I just realized that we can simplify the JS a lot.

luksak’s picture

Status: Needs review » Needs work
markdc’s picture

This issue resulted in me discovering a problem with our credit card payment module, Commerce Paymill. Payments were failing for customers whose shipping cost was refreshed after choosing credit card payment, which was about 90% of our customers. AFAICT, the card amount is tokenized for the gateway before the shipping cost is recalculated.

By moving payment information to the next checkout pane I could avoid these errors. But this is just a workaround.

I suspect the issue lies with the Paymill module, as this would have been noticed by now if it affected the more popular gateways, like Authorize.net.

remaye’s picture

I successfully applied patch in #93 and experienced the following issue :

When I first select a country and complete the address fields it first works fine : automatically display the right shippment method(s)

If then I select another country, it recalculate the new address fields corresponding to the new country, then come immediatly back to the country I selected first. So that it's impossible to change the country without reloading the page ...

Note this happens only after the address has been fully completed once and the shippment method(s) displayed.
Until the shippment method(s) is calculated, changing the country selector is working fine.

[ D 8.6.13 / Commerce 8.x-2.13 / Com. Shipping 8.x-2.0-beta6 ]

mglaman’s picture

  1. +++ b/js/shipping_checkout.js
    @@ -0,0 +1,50 @@
    +        $(window).once('commerce-shipping').on('load', function () {
    +          $.fn.commerceCheckShippingRecalculation(shippingSettings);
    +        });
    

    Behaviors attach once the DOM has been loaded. We just need a "once" on the wrapper

  2. +++ b/src/Plugin/Commerce/CheckoutPane/ShippingInformation.php
    @@ -201,6 +207,18 @@ class ShippingInformation extends CheckoutPaneBase implements ContainerFactoryPl
    +        'recalculateButtonSelector' => '[data-drupal-selector="edit-shipping-information-recalculate-shipping"]',
    

    Should the drupal-selector be hardcoded like this? It is generated later in the doBuildForm method after the buildForm method is invoked but before process methods.

    We should attach a custom #process callback which generates the #attached properties.

  3. +++ b/tests/src/FunctionalJavascript/CheckoutPaneTest.php
    @@ -196,7 +196,7 @@ class CheckoutPaneTest extends CommerceBrowserTestBase {
    -  public function testSingleShipment() {
    +  public function testSingleShipment($autocalculate = TRUE) {
    
    @@ -448,6 +456,18 @@ class CheckoutPaneTest extends CommerceBrowserTestBase {
    +  /**
    +   * Tests checkout when the auto calculate is disabled.
    +   */
    +  public function testAutoCalculateDisabled() {
    +    $checkout_flow = CheckoutFlow::load('shipping');
    +    $checkout_flow_configuration = $checkout_flow->get('configuration');
    +    $checkout_flow_configuration['panes']['shipping_information']['auto_recalculate'] = FALSE;
    +    $checkout_flow->set('configuration', $checkout_flow_configuration);
    +    $checkout_flow->save();
    +    $this->testSingleShipment(FALSE);
    +  }
    +
    

    We can use a dataProvider for this, instead of invoking the test twice manually.

  4. +++ b/tests/src/FunctionalJavascript/CheckoutPaneTest.php
    @@ -224,7 +224,13 @@ class CheckoutPaneTest extends CommerceBrowserTestBase {
    +    if ($autocalculate) {
    +      // Wait for the recalculate button to be clicked.
    +      $page->waitFor(0.3, function() {});
    

    We can use \Drupal\FunctionalJavascriptTests\JSWebAssert::assertWaitOnAjaxRequest

  5. +++ b/tests/src/FunctionalJavascript/CheckoutPaneTest.php
    @@ -376,6 +383,7 @@ class CheckoutPaneTest extends CommerceBrowserTestBase {
    +    $checkout_flow_configuration['panes']['shipping_information']['auto_recalculate'] = FALSE;
    

    We shouldn't turn off auto calculate, as it should be aware no shipping profile is required.

mglaman’s picture

Status: Needs work » Needs review
StatusFileSize
new12 KB

Here is an updated patch. Items 2 and 5 from my previous comment still stand.

mglaman’s picture

StatusFileSize
new11.73 KB

#2 needed to be handled in after_build. And #5 was a non-issue.

lisastreeter’s picture

This is working well for me.

gge’s picture

Applied #99 and I'm having the same problem as #96...
I think that somehow the depended fields should be cleared when parent changes its value.

#96 describes a problem with the country selector, but the same problem also appears when having one country with subdivisions.

mglaman’s picture

Issue tags: +Needs tests

We need to update the test to

1. Change the country selection after providing a full address, verify it works.
2. Use a country with subdivision selection and verify input is reset.

There is supposed to be AJAX callbacks which wipe user input ($_POST) to reset the forms. We need to expand the test coverage and verify it is failing and then investigate the fix.

nicolasgraph’s picture

Thanks for your work on this issue ; I also applied #99 and #96 is still up to date for me.
When an address is already provided, changing the country fails.

replicaobscura’s picture

This is generally working well for me when testing except for:

1. The issue mentioned in #96, and
2. It doesn't seem compatible with the new Address Book part 2 patch which adds a select field to select existing addresses. (https://www.drupal.org/project/commerce/issues/3053165)

Update: Actually it does seem to work in some cases, #2 might be an interaction with some other customizations I'm using. Testing further.

replicaobscura’s picture

Scratch that, I'm not sure why automatic shipping calculation wasn't working for me initially when testing this patch, but I can no longer reproduce the issue, this patch and that one seem to be working well together.

tamerzg’s picture

Status: Needs review » Needs work

Still getting issue mentioned in #96 with patch in #99.

lisastreeter’s picture

StatusFileSize
new13.83 KB

I'm also seeing the bug described in #96 and have attempted to add a test for it.

lisastreeter’s picture

StatusFileSize
new14.21 KB

Missing use statement.

lisastreeter’s picture

StatusFileSize
new14.55 KB

That didn't work to verify bug. Trying variation on that. (Apologies for issue spam--can't get functional javascript tests running on my local at the moment.)

lisastreeter’s picture

StatusFileSize
new18.08 KB

Fix to existing test and new test for checking country with subdivision possible bug.

lisastreeter’s picture

StatusFileSize
new18.38 KB

Tests are failing as expected, to match the bug reported in #96. I've updated the subdivision test here, just to include the autocalculate dataProvider, to verify that the test only fails in the autocalculate scenario.

Also, while testing through the UI, I agree with this statement in comment #101:

I think that somehow the depended fields should be cleared when parent changes its value.

The #after_build in the checkout pane (autoRecalculateProcess) is running. But the #after_build of the address element (clearValues) is not. Perhaps the JS is blocking it?

Somehow, we need to make sure that clearValues() happens before the commerceCheckShippingRecalculation() method in the JS runs, so that the cleared input values will register, and the recalculation won't happen.

Another couple items to note:
If you choose a country and then enter some of the dependent values (like US and then State and postal code) but you don't fill in all the required fields, you can still change to another country. The dependent filled-in values are cleared.

You can also avoid the bug with the following sequence of events:
1. Fill in an address completely.
2. Autocalculate runs.
3. Delete one of the required values, like First name or State so that the address is no longer complete.
4. Then change the country. The dependent fields are cleared as expected.

So the bug specifically only happens if you've got a complete address and you change a field, like the Country, that should result in dependent values clearing. If the autocomplete JS runs (because you've still got a complete address), the fields won't get cleared and the form is broken.

lisastreeter’s picture

StatusFileSize
new19.17 KB

I've made a change to the JS that seems to fix bug #96, at least when testing locally. BUT... it may be overly restrictive and create other problems. Essentially, I've updated the "recalculate" logic so that it won't run if the form element that's been updated has dependent form elements that should be cleared as a result of the change.

One problem I can see with this approach is that if the dependent form elements aren't actually required, then if the form was complete before they were cleared, it's still complete with respect to recalculate-shipping. Perhaps it would just be better to handle the dependent-form-element-clearing and go ahead with recalculating?

So take the logic that's in place and clear values instead. For reference, the logic that has been added comes from the address form element in the address module: Drupal\address\Element\Address::clearValues().

Or...perhaps there's a way to just make sure that the clearValues() #after_build callback will always run before the recalculate js. I'm not sure what the best approach. Posting my wip patch here, partly just to see whether it clears the functional js tests.

jwwj’s picture

I'm not getting the patch in #112 to apply against 2.x-dev. Are you patching against the *-dev branch or the beta6 release? Or do I need to apply some other patches as well?

lisastreeter’s picture

@jwwj Yes, the patch should work with the dev branch: composer require 'drupal/commerce_shipping:2.x-dev'

Do you have any other patches that might be causing the conflict?

jwwj’s picture

I was applying the patch #2 from https://www.drupal.org/project/commerce_shipping/issues/2934142. But I also tried removing that patch and only applying this patch without success... I'll have another look next week when I have time to test around with the other dependencies to see if something else is causing issues.

Did you apply this against the latest Drupal core as well (8.7.6) or some other version of core? Thinking if something has changed in core that might affect things (though unlikely)...

jwwj’s picture

So I did another retake on this, and for me the #112 only applies if I remove the changes in src/FunctionalJavascript/CheckoutPaneTest.php from the patch. Used commerce_shipping@beta7, but same thing happens with the -dev branch for me.

Another issue I'm seeing now that I got the patch to apply is that when I have Auto recalculate shipping costs activated in the checkout flow, whenever I change a value in the shipping information form and tab to the next field, the form loses focus. E.g. if I change the "First name" and tab over to the "Last name" field, once the ajax refresh returns (that was triggered by the change in the First name field) the form has lost focus and anything I type just hits thin air. I have to click/tab around again to the field I want to modify in order to continue typing. I'm assuming this has something to do with the ajax call re-inserting the entire shipping info form when it returns, but don't know Drupal ajax logic well enough to suggest a fix. Not sure this is a major issue atm. because it only happens once the entire form is filled out and one goes back to edit a field value, which probably isn't what most customers will end up doing. Even then, my guess is the most common case is that the customer has to correct the value of a single field, in which case this loss of focus doesn't matter that much.

berdir’s picture

StatusFileSize
new19.45 KB

Here's a basic reroll. @bojanz is pretty busy on commerce_shipping these days, there are some pretty big changes to that test, but looks like it didn't work before either?

Just did a minimal reroll for now so the code isn't lost.

jwwj’s picture

Patch #117 worked for me on using commerce_shipping@beta 7 and commerce@2.14, thanks!

mellowtothemax’s picture

Patch #117 worked for me too on dev.

finex’s picture

StatusFileSize
new16.42 KB

Hi, I've updated the patch to the latest -dev version (the following one doesn't apply anymore).

tonytheferg’s picture

Wouldn't it be a better UX/UI to have shipping options output on a subsequent page as it was in 7? I'm just getting to know the new checkout flow, but the new UI seems a little bit confusing. Or am I overlooking an obvious benefit here?

finex’s picture

Updated patch to latest -dev.

finex’s picture

Re-updated patch.

finex’s picture

StatusFileSize
new16.45 KB

Fixed missing "}" on patch.

jon pollard’s picture

Thanks FiNeX that's now working for me. The only thing that is still a bit glitchy is if you add a shipping address and then edit your shipping address it doesn't re-calculate unless you opt to 'go back' and then it re-calculates.

mbovan’s picture

Status: Needs work » Needs review
StatusFileSize
new16.29 KB
new5.18 KB

Rerolled #117 patch on top of latest 8.x-2.x branch and fixed deprecations in the tests.

#120 removes commerce shipping JS libraries.

Also, I reverted changes in Drupal\commerce_shipping\Plugin\Field\FieldWidget\ShippingRateWidget. It does not look like those are necessary.

mbovan’s picture

Issue tags: -Needs tests

Removing "Needs tests" tag.

flocondetoile’s picture

Patch #126 works fine on latest -dev (commit 8921b07). Thanks.

jon pollard’s picture

This is all working beautifully - one last bit... if you are logged in and have multiple addresses in your address book, selecting a different address does not trigger a recalculation of P&P.

sasanikolic’s picture

StatusFileSize
new16.29 KB
new751 bytes

Rerolled against latest 8.x.2.x.

There was one accessibility issue with the latest #126 patch.
While using the keyboard to fill out the form, when the Recalculate button was triggered, the focus was completely lost and you needed to start all over from the top of the form. The issue was, that the button was hidden with js-hide, which hides the button with display: none. This makes the button unfocusable. By changing it to visually-hidden, the button gets the focus and you can continue from there on. Note that this still makes you skip fields that are between the latest form element that had focus and the hidden button, but at least flow is much improved.

Status: Needs review » Needs work

The last submitted patch, 130: 2849756-130.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

p4trizio’s picture

I confirm #129: selecting a different address does not trigger a recalculation (patch #126 applied)

flocondetoile’s picture

Status: Needs work » Needs review
StatusFileSize
new685 bytes
new16.48 KB

re #129 and #132 : selecting a different address should now trigger a recalculation.

flocondetoile’s picture

Status: Needs review » Needs work

Ha, patch #133 has been made against beta8 from #130. Looks like it a needs reroll

flocondetoile’s picture

Status: Needs work » Needs review
StatusFileSize
new16.65 KB

patch #133 rerolled against latest -dev

Status: Needs review » Needs work

The last submitted patch, 135: 2849756-135.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

flocondetoile’s picture

With patch #135, selecting the option "Enter a new address" trigger a recalculation. We don't want that.

flocondetoile’s picture

Status: Needs work » Needs review
StatusFileSize
new27.85 KB
new12.93 KB

Fix the case when selecting the option "Enter a new address" this trigger a recalculation. The recalculation is now only trigerred if an existant profile is selected from the select list.

Also fix existing test.

Status: Needs review » Needs work

The last submitted patch, 138: 2849756-138.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

flocondetoile’s picture

Status: Needs work » Needs review

I've got too on my local environment some random failures cause by some curl error. But not always :-/

flocondetoile’s picture

Status: Needs review » Needs work
p4trizio’s picture

@flocondetoile thanks for the patch but I have a problem with the timeout function set to 500ms. Indeed, most of the times 500ms is not sufficient to complete the ajax triggered by the change of the address.
I think we could solve this with a loop function until a condition is met, but I'm not a JS expert so I'll wait for some feedback on the following solution:

Eg.
1. assign a class to the select
$(this).addClass('ajax-triggered');

2. replace

setTimeout(function () {
  Drupal.commerceCheckShippingRecalculation();
}, 500);

with
loop(this);

3. add the loop() function

function loop(el) {
  setTimeout(function () {
    var id = $(el).attr('id'); //this is necessary to get the new element
    el = $('#' + id);
    if($(el).hasClass('ajax-triggered')) {
      loop(el);
    } else {
      Drupal.commerceCheckShippingRecalculation();
    }
  }, 100, el);
}

What do you think?

agoradesign’s picture

Issue tags: +Needs reroll

patch doesn't apply anymore

flocondetoile’s picture

thanks for the input @p4trizio ! I'm not really a front-end developer, let alone a JS expert. :-) But your suggested approach looks like more robust than the arbitrary timeout I set, definitively. Will try to update the patch soon.

mbovan’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new24.45 KB
new9.59 KB

Rerolled patch #138 and made a few improvements to tests.

mbovan’s picture

+++ b/src/Plugin/Commerce/CheckoutPane/ShippingInformation.php
@@ -206,6 +214,14 @@ class ShippingInformation extends CheckoutPaneBase implements ContainerFactoryPl
+    // Prepare the form for ajax.
+    // Not using Html::getUniqueId() on the wrapper ID to avoid #2675688.
+    $pane_form['#wrapper_id'] = 'shipping-information-wrapper';
+    $pane_form['#prefix'] = '<div id="' . $pane_form['#wrapper_id'] . '">';
+    $pane_form['#suffix'] = '</div>';

This part was removed in #3114994: Rework the ShippingInformation pane ajax but I think we still need it here.

Status: Needs review » Needs work

The last submitted patch, 145: 2849756-145.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

flocondetoile’s picture

StatusFileSize
new24.81 KB
new1.09 KB

Added suggested improvments from #142

flocondetoile’s picture

Status: Needs work » Needs review

trigger the bot

Status: Needs review » Needs work

The last submitted patch, 148: 2849756-148.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

ayalon’s picture

There is a bug in the latest patch. After entering a full address profile, the country selector (select field) does not trigger a recalculation of the address.

I think, the jQuery selector in the patch only targets ":input.required" which means it will not trigger on country change.

This is an issue because changing the country is very likely also needs a recalculation of the shipping costs.

Deithso’s picture

I have my own script the enable auto recalculating the shipping on country change, i tried the patch provided by @flocondetoile
it works fine, however with the last version of the module 2.17 i have 2 errors

TypeError: Argument 2 passed to Drupal\commerce_shipping\ShipmentManager::applyRate() must be an instance of Drupal\commerce_shipping\ShippingRate, null given,

To fix it i edited the file

Drupal\commerce_shipping\Plugin\Field\FieldWidget\ShippingRateWidget

And added a test to set the default value

 $selected_value = NestedArray::getValue($form_state->getValues(), $parents, $key_exists);
+ $exists_selected_value = array_key_exists($selected_value, $element['#options']);   
+	if(!$exists_selected_value){
+		$selected_value = $element["#default_value"];
+	}
if ($selected_value) {

Now i have this error message, even if the new rates are displayed

It occurs because of the $selected value which doesn't exist anymore

An illegal choice has been detected. Please contact the site administrator.

Deithso’s picture

Hey,

I solved the error message

An illegal choice has been detected. Please contact the site administrator.

I have to bring the removed lines from the previous version

In \Plugin\Commerce\CheckoutPane\ShippingInformation;

if ($recalculate_shipping) {
      // Use the shipping profile set in validatePaneForm().
      $shipping_profile = $form_state->get('shipping_profile');
    }
    else {
      // Take the processed profile from the inline form, it
      // might have been pre-filled from the address book.
      $shipping_profile = $inline_form->getEntity();
    }

Those lines have been replaced by line bellow

$shipping_profile = $form_state->get('shipping_profile');

Even the earlier error i got is now fixed, so i revoked the fix

TypeError: Argument 2 passed to Drupal\commerce_shipping\ShipmentManager::applyRate() must be an instance of Drupal\commerce_shipping\ShippingRate, null given,

finex’s picture

Hi, I'm trying the patch but it has an usability problem: when you update a field and trigger the shipping recalc, the focus is lost. For example I press TAB or click on the next field, and the focus is gone.

I've tried to save the current focused element before the recalc, and set after the recalc using a timeout but the cursor is always set at the start of the input field, and it doesn't work on
elements.

The original code is the line with the "trigger()" method, this is the code I've tried. What do you think about?

// Get the current focus:
var currentFocus = $("input:focus").data("drupalSelector");

// Trigger the mousedown event on the shipping recalculation button.
$(shippingSettings.wrapper).find(shippingSettings.recalculateButtonSelector).trigger('mousedown');

// Set the focus
setTimeout(function(){
  $('input[data-drupal-selector='+currentFocus+']').focus();
}, 200);
problue solutions’s picture

There is a bug in the latest patch. After entering a full address profile, the country selector (select field) does not trigger a recalculation of the address.

I think, the jQuery selector in the patch only targets ":input.required" which means it will not trigger on country change.

This is an issue because changing the country is very likely also needs a recalculation of the shipping costs.

Any idea how to fix this?

Bogdan Nedelcu’s picture

StatusFileSize
new972 bytes

On country change, the ajax call for recalculating shipping rates is failing as the form has not been filled yet. To prevent this, you can skip applying rates in ShippingRateWidget.php if there is no rate to apply.

au_dave’s picture

StatusFileSize
new9.31 KB

This patch doesn't apply to the latest dev version of commerce_shipping.

I've rerolled it using #148 & #156 and improved the configuration summary.

shabana.navas’s picture

StatusFileSize
new2.75 MB

I've done testing on a fresh new install of the Orange Ecommerce Profile with the latest version of Drupal Commerce and Drupal Core and using the patch in #157 and, for most cases, the Auto Recalculate works really nice. It works fine with reusing profiles, adding a new address, changing addresses, changing zip codes, changing to an existing profile, etc.

However, I did notice a couple of things with my testing so far:

  1. No default is selected for shipping method (visually) when changing addresses, but we can still "Continue to Review"
  2. - When continuing to review page, the first shipping method is shown as selected
    - See attached gif

  3. When a method is already selected and you "Continue to Review", then, return, and change the country and the previously selected method is no longer available for that address
  4. - An illegal choice has been detected error is displayed
    - Some of the available shipping methods disappear
    - Can continue to next page regardless
    - Missing shipping methods reappear when we go back to the "Order Information" page again
    - See attached gif

I'm continuing to test and will update with any further findings.

shabana.navas’s picture

StatusFileSize
new2.04 MB
new1.93 MB

Update from further testing:

  1. With auto-recalculate config turned off and we reuse a profile with a different country than the default selected address when the chekcout page first loads
  2. - We get a "Shipping method" error
    - When we hit 'Calculate Shipping', we get an "Illegal choice detected.." error
    - See attached gif

  3. Once we initially create an address and complete the address and the shipping recalculates, then, when we change the zip code to an invalid one for that state
  4. - We get a zip code error, which works as expected (should it clear the address fields at this point?)
    - Then, when we change the state to the correct one, it doesn’t recalculate, even though the address is complete
    - Deleting the city/address line 1 completely and re-entering still doesn’t recalculate
    - Only recalculates after a couple of tries
    - See attached image

  5. - Removing the state/zip code does not delete/clear the dependent fields like street address and locality

So, these are the issues that I've found with testing patch #157. I've tested it under the following scenarios (based on the comments above):

- [x] Tests passing
- Tests are failing
- [x] Different themes
- [x] Orange E-Commerce Starter
- [x] Seven
- [x] Bartik
- [x] Stark
- [x] Recalculating after choosing credit card
- [x] Check focus when using keyboard to fill out form
- [x] Fill in address completely, recalculate runs, delete one of the required fields, see if all dependent field are cleared
- [x] Zip Code invalid
- [x] With phone number field
- [x] Changing country after recalculation
- [x] With auto-recalculate config off and on
- [x] Reusable profiles
- [] Commerce USPS
- [ ] Couldn’t try out USPS but works w/ UPS

I'm currently running tests in the background, will update with info on which tests are failing. And hopefully start digging into these issues and see if we can address them.

CaptainPinkey’s picture

Learned the hard way, that the patch #148 (and I think most others) make problems for countries that have the administration area or something similar in the address.

        else if ($(this).hasClass("administrative-area")) {
          if ($('.dependent-locality').length || $('.locality').length) {
            addcheck = false;
          }
        }
        else if ($(this).hasClass("locality")) {
          if ($('.dependent-locality').length) {
            addcheck = false;
          }
        }

This lines prevent the recalculation when entering for example the province in an Italien address. The province field is ignored for the auto recalculation but is also the last field of the address, and therefore potential the last required field to be filled.
I don't see the reasoning why to ignore these fields. At least in my case, where the the shipping methods are only filtered by the country, removing these lines works great.

khiminrm’s picture

I've installed Drupal Orange by using 'Orange E-Commerce Profile' and tried to reproduce #158, #159. I couldn't reproduce issues in #158 - after changing country there was always selected first shipping method as default. I also couldn't reproduce 1. in #159.

But I was able to reproduce 2. in #159 - error of zip code was gone only if changed value in street or cite and clicked anywhere outside the field. By changing state recalculate wasn't triggered.

Also 3. in #159 is reproducible but I'm not sure if it's a bug or expected behavior.

I've checked logic in Drupal.behaviors.commerceShippingRecalculate. Only fields like first name, last name, street address, city, zip code trigger 'Drupal.commerceCheckShippingRecalculation' on change event. Is this correct behavior?

khiminrm’s picture

StatusFileSize
new9.94 KB
new2.78 KB

I think logic in Drupal.behaviors.commerceShippingRecalculate was incorrect. I've re-written those part.
Also we need to update tests.

khiminrm’s picture

StatusFileSize
new13.97 KB
new3.78 KB

Trying to fix existing Javascript tests by setting 'auto_recalculate' setting to FALSE.

khiminrm’s picture

StatusFileSize
new16.24 KB
new2.64 KB
khiminrm’s picture

StatusFileSize
new24.19 KB
new13.95 KB

Updated tests.

lisastreeter’s picture

I've been testing with patch #164. I have several stored profiles in my address book, for different countries. When I change from one selection to another, the shipping options are appropriately updated. However, if I try to edit an existing address, changing its country does not update my shipping options as it should. Similarly, if I use the "Enter a new address" option, the initial shipping method options correspond to whichever profile was previously active. And then if I select a new country, the shipping options do not update correctly; they remain the same.

If I turn off the auto-recalculate option, all of the above works as it should. So there are still issues to be resolved.

khiminrm’s picture

StatusFileSize
new4.45 KB

Updated tests again. I noticed that $this->assertSession()->assertWaitOnAjaxRequest(); can doesn't wok after $page->fillField($address_prefix . '[' . $property . ']', $value);. I tried to add some delay by adding:

 // Give some time for script trigger ajax.
 $this->assertSession()->waitForElementVisible('css', '.test-wait', 10);

It can be due timeout in javascript:

 $(shippingSettings.wrapper).find(shippingSettings.recalculateButtonSelector).trigger('mousedown');
      }, 100);

Not sure if it's right solution. Maybe we need to add some class or change attribute on form element to wait while script will trigger form submit - press on button. Or use similar timeout in tests.

khiminrm’s picture

khiminrm’s picture

StatusFileSize
new24.82 KB
new4.45 KB

Added patch with updated tests mentioned in #167

khiminrm’s picture

StatusFileSize
new25.48 KB
new4.09 KB

Removed time limit before clicking on Recalculate, added class to form on required input changed, used class in tests.
I tried to make javascript working according description of the issue - all required fields should be not empty before triggering recalculation.

For now after changing country, some fields can be empty after ajax and shipping method won't be changed until values for all required fields will be inputted.

khiminrm’s picture

StatusFileSize
new25.67 KB
new1.68 KB
khiminrm’s picture

khiminrm’s picture

StatusFileSize
new24.41 KB
new1023 bytes
lisastreeter’s picture

@khiminrm You were correct -- I think I was neglecting to enter all required fields when I tested #164. Sorry about that!

I've been testing the latest patch, #173. All is working well for me. And I've manually walked through the steps in the first failing test (ProfileFieldCopyTest::testCheckout) to see whether I encountered any weirdness that might relate to the "Curl error thrown..." error report. But I was able to go back and forth between the Order Information and Review steps, changing/copying shipping/billing addresses, valid/invalid postal codes, etc. without triggering any noticeable errors. So no insight there.

Aside from the failing tests, I think this patch is in good shape. Everything I tried through the UI tonight worked as expected/intended.

sumi’s picture

Tested patch #174 and here is what I found:

Required select list fields do not trigger shipping recalculation. Most noticeable is State field (USA, Australia, India, Mexico, Venezuela). But there are also Island (Cayman Islands, St. Kitts & Nevis), Province (Canada, San Salvador, Italy, Somalia, Spain, Indonesia), District (Nauru), Prefecture (Japan), Department (Colombia), Oblast (Russia), Parish (Jamaica), Emirat (United Arab Emirates) and Area (Hong Kong SAR China). In some cases lack of trigger on these select lists means that there is no way to trigger shipping recalculation since form doesn’t have city or post/zip code (United Arab Emirates, Indonesia, Hong Kong SAR China, Cayman Islands).

Also shipping recalculation is not triggered once all required fields in the form are filled in if last field that we fill in is not City, Post/Zip code or one of the others that actually trigger shipping recalculation. So in case if we miss filling in First name (Last name, Street address) and fill in all other required fields and get back to that one in the end shipping recalculation is not triggered. In cases when address form only has First name, Last name and Street address and no other required fields this means that shipping recalculation is never triggered (Antigua & Barbuda, Macao SAR China).

khiminrm’s picture

StatusFileSize
new24.44 KB
new476 bytes

@lisastreeter, @Sumi, thanks for testing!

I've fixed recalculation after changing value in select for administrative area, described in previous comment. Not sure about other fields as in description of the issue we have:
We don't care about the name, organization, address lines.

khiminrm’s picture

StatusFileSize
new25.65 KB
new1.09 KB

Tried to fix tests.

pivica’s picture

StatusFileSize
new26.24 KB
new6.9 KB

Did a number of improvements:

  • Refactoring and simplification of code and introduction of local jQuery vars,
  • Run context document behaviour code only once,
  • Use context in behaviour selector,
  • Adding more explanation comments,
  • Support adding of additional required not supported profile shipping fields. For example if you add a required telephone field as a last field to shipping profile fields ajax shipping recalculation is not triggered. New patch is fixing this.

One additional thing, i am not sure why we have `':not(.chosen-container)' filter in:

$wrapper.find(':input.required').filter(':not(.chosen-container)').each(function () {
  if (!$(this).val()) {

I've searched all the code for `chosen-container` CSS class (core and contrib) and I can't find any code that is setting this class. The only thing i can figure is that this filter came from D7 version and it is not doing anything meaningful now, or i am missing something. Can we remove it?

wgsimon’s picture

I am testing patch #178 and the main issue I have is, as mentioned in #159, when clicking on 'Continue to Review' before the shipping has been updated, the shipping is either incorrect or I get the 'Illegal choice detected...' error. This last error appears when a shipping method becomes unavailable due to the change of country. To avoid these situations, I have disabled the 'Continue to Review' button during the recalculation by adding a line to shipping_checkout.js as follows:

    if (recalculate) {
      // Disable the 'Continue to Review' button while recalculating.
      $('[id^=edit-actions-next]').prop('disabled', true);      
      // Trigger the mousedown event on the shipping recalculation button.
      $wrapper.find(shippingSettings.recalculateButtonSelector).trigger('mousedown');
    }

This seems to work for me.

finex’s picture

@wgsimon: thanks, I was experiencing the same issue :-)

pivica’s picture

> This last error appears when a shipping method becomes unavailable due to the change of country.

Yeah, my tests didn't include a country field for now, so I didn't saw that error. If i have time later will try to check it.

agoradesign’s picture

I can confirm that there are some problems left, when you play around with changing country

dubs’s picture

This issue overlaps a little with this issue too, certainly in terms of UX and expected behaviour from changing an address: -

https://www.drupal.org/project/commerce_shipping/issues/2898118

The referenced issue is to do with the order summary total.

Changing a shipping address (think country) leaves the original shipping cost in place in the order summary, which is confusing for the visitor.

Another unrelated issue is the tax. If you change country then tax rules are different so the order total should update too. Right now it leaves the first tax rate in place until you go to the next checkout step, which is confusing as it looks like they will pay tax. Probably the two issues should overlap to solve a common problem, or maybe not, but I though it was worth mentioning :-)

jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new228.9 KB

@Dubs: #2898118: Update the order summary via AJAX when a shipping rate is selected should be handled separately IMO as this will postpone the auto recalculation fix even more...

I've been working on this issue and decided to rewrite the JS from scratch as I wasn't really happy with the logic we had to detect whether dependent fields were filled and also because we've been dragging unnecessary/outdated logic from the early patches.

Additionally, I made couple of other changes to the patch:

  • The auto recalculation doesn't make sense and shouldn't be active if the "Hide shipping costs until an address is entered" setting is not checked. Therefore, the auto recalculate setting isn't visible if a shipping profile is not required to see shipping rates.
  • While expanding the tests, I encountered another issue that I fixed. Whenever another "stored" address was selected, I was getting the infamous 'An illegal choice has been detected' error, this is due to the fact that the selected rate wasn't cleared when the address was changed.
  • I'm using the "js-hide" class to hide the recalculate rates
  • I also addressed the comment #178 and the submit button is now being disabled while the rates are being recalculated in order to prevent the "Illegal choice" error on submit due to an invalid rate being selected.

Tests are now passing locally, and we should have the necessary tests coverage to ensure the shipping rates are automatically recalculated whenever another stored address is selected, updated, or whenever a new address is entered.

Finally, I've decided to follow core and use ES6 to modernize our JS (See https://www.drupal.org/node/2873849).

The JS file that needs to be edited is now "shipping_checkout.es6.js". After modifying it, the command "yarn build:js" should be executed in order to build the JS.

As a side note, it'd be interesting to implement a "loader" or something in order to get a visual indication that the shipping rates are being recalculated similar to when the "recalculate shipping" button is present.

Hopefully this issue is now fixed so can finally move forward after all these years :p.

Not posting an interdiff since besides the setting and the library inclusion, I rewrote the JS from scratch and didn't keep any of the prior changes to the tests.

Note that I'm not 100% sure about the necessary packages in packages.json (mostly stolen from core) in order to build the JS.

jsacksick’s picture

StatusFileSize
new228.79 KB
introfini’s picture

StatusFileSize
new35.11 KB
new34.77 KB

Finally, thanks!

I've tested it in two different projects, and it worked as expected.

(Attached the result with and without the patch applied.)

agoradesign’s picture

worked for me too

agoradesign’s picture

Status: Needs review » Reviewed & tested by the community

let's set this to RTBC :)

renrhaf’s picture

+1 RTBC, works on our project ! Thanks @jsacksick !

The last submitted patch, 162: 2849756-162.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

The last submitted patch, 169: 2849756-169.patch, failed testing. View results

ayalon’s picture

Wow! Finally! Thanks a lot for the work and effort on this issue. I tested the patch and it also works on our side.

Additionally I tested the patch together with #2898118: Update the order summary via AJAX when a shipping rate is selected and they both work together.

rgpublic’s picture

Patch #185 contains a lot of unnecessary stuff (eslintrc.json, yarn.lock). Perhaps these should be removed.

Besides that, I can only corroborate that in my experience it's a very good idea to have an approach that doesn't actually save the order. Trying to solve this myself for a long time I always failed because I ended up needing to save the order which triggers all kinds of things you don't want to happen.

Especially in conjunction with reusing shipping/billing addresses etc. For example, if you come back to the shipping address page and e.g. change the country but don't click save, close your browser, come back later, you would expect your old shipping address still in place because you never clicked save. All these edge cases fall apart if you save the order automatically just for recalculation purposes. So, indeed, the trick is to apply the changes without actually saving the order.

jsacksick’s picture

Patch #185 contains a lot of unnecessary stuff (eslintrc.json, yarn.lock). Perhaps these should be removed.

These are necessary in order to build the JS code, I invite you to read https://www.drupal.org/node/2873849.

sander wemagine’s picture

I can confirm patch #185 works. Would be great if this would be added to the release.

I did found one minor issue which really isn't important (in my opinion). The shipping pane with this patch (and minor issue) is so much more usable than without it.

1. Enter the last required address field ("city" in my case)
2. Keep focus on the element
3. Click the "Continue to review" button
4. An error appears: "An illegal choice has been detected. Please contact the site administrator.". This happens because the onChange didn't trigger yet.

Solution might be by replacing the onChange event listener with a onInput with a delay?

jsacksick’s picture

OnInput might make sense in a followup, I'd really not delay this functionality further.

If we change to using onInput, then we'll need different code to account both for "input" and "select" elements whereas onchange works for all.

  • jsacksick committed 6ba4c89 on 8.x-2.x
    Issue #2849756 by khiminrm, bmcclure, jsacksick, ransomweaver,...
jsacksick’s picture

Status: Reviewed & tested by the community » Fixed

🥳🥳 Committed!! Thanks everyone!

dubs’s picture

Wow, amazing! Thank you :-)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

inwebsol’s picture

Thank you so much for this. And sorry if this has already been explained but I've updated to the the latest version and I still see the recalculate button. Is there a new setting to configure to make it hidden and the shipping costs to be recalculated automatically? Thank you again.

nno’s picture

@inwebsol

Under Checkout flows ... Shipping information ... both "Hide shipping costs until an address is entered" and "Auto recalculate shipping costs when the shipping address changes" need to be enabled to hide the "Recalculate shipping" button.

beniamin.szabo’s picture

The automactic recalculation is not triggered when selecting a profile from the addressbook.

mach3.zone’s picture

We still struggle with this issue as it seems others do (#203). For now I added an OrderProcessor with a higher priority than the EarlyOrderProcessor and force a refresh with:

    if ($this->shippingOrderManager->hasShipments($order)) {
      $order->setData(ShippingOrderManagerInterface::FORCE_REFRESH, TRUE);
    }

Anyone else troubled? Probably self-imposed . 🙈

munti’s picture

The problem still exist in 8.x-2.x-dev , 14 Feb 2025.
Patch #185 faild.
Is there a new updated patch?