Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shipping method radios become disabled when checkout page refreshed #7497

Closed
wsagen opened this issue Nov 21, 2016 · 39 comments
Closed

Shipping method radios become disabled when checkout page refreshed #7497

wsagen opened this issue Nov 21, 2016 · 39 comments
Assignees
Labels
bug report Component: Checkout Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development

Comments

@wsagen
Copy link

wsagen commented Nov 21, 2016

Preconditions

  1. Magento CE v2.1 installed
  2. Tested with UPS carrier enabled using UPS XML endpoint and Flat rate enabled

Steps to reproduce

  1. Add product to the cart
  2. Proceed to checkout as a guest
  3. Enter valid address details
  4. Wait for shipping rates to be displayed
  5. Refresh page (Ctrl + R for example)

Expected result

  1. Page reloads showing shipping rates with active radio buttons

Actual result

  1. Page reloads with shipping rates but radio buttons are disabled

checkout

We've also observed this on initial checkout page load but not able to provide instructions to reliably reproduce this every time.
@wsagen
Copy link
Author

wsagen commented Nov 21, 2016

This is affecting several live clients at present. Work around is to modify the address fields which refreshes the shipping rates and radio buttons become selectable again.

@hpatelgit
Copy link

hpatelgit commented Nov 22, 2016

Yes i am also getting same issue when add new address at checkout and then on refresh page radios become disabled.

Even i have upgrade magento with latest version.

Thanks

@SerhiyShkolyarenko SerhiyShkolyarenko self-assigned this Nov 24, 2016
@SerhiyShkolyarenko SerhiyShkolyarenko added the Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development label Nov 24, 2016
@SerhiyShkolyarenko
Copy link
Contributor

SerhiyShkolyarenko commented Nov 25, 2016

Reproduced. Created internal issue MAGETWO-61384. Thank you!

@Tapin1
Copy link

Tapin1 commented Dec 6, 2016

Any fix for this issue?

@SerhiyShkolyarenko
Copy link
Contributor

@Tapin1 issue is in queue for fixing. We don't have estimates yet.

@rsisco
Copy link
Contributor

rsisco commented Dec 15, 2016

We too are experiencing this issue on Magento 2.1.2 and can reproduce the problem with the following steps:

  1. Sign into an existing (or create a new) customer account with an address in the address book
  2. Add one or more items to the shopping cart
  3. Click Checkout in the mini cart
  4. Click the New Address button on the shipping page
  5. Complete the new address form and submit

The radio buttons will then all disable after a few seconds although the radio button labels remain clickable.

@hpatelgit
Copy link

I have upgrade magento with latest 2.1.3 and still this issue is present.

@Frits1980
Copy link

Is their anyone who knows which file is setting the disabled attribute to the html input field? I've searched but I can't find the file. Because I really need to work around this issue for the time being.

@reijervano
Copy link

Has anyone a fix for this?

@Frits1980
Copy link

Actually the problem disappeared when I updated all my extensions.

@reijervano
Copy link

This problem is still there in the latest version!

@ddeppner
Copy link

ddeppner commented Feb 3, 2017

I'm seeing this in 2.1.3. It's a pretty serious bug as it impacts checkout and for a customer that isn't aware of a workaround (basically EVERYBODY), if they get the bug, they cannot complete their checkout. Triggering this bug is hard. It happens sometimes and not other times. I've seen it happen after adding addresses, or when going back to the shipping screen to change sometime after previously advancing to the payment screen. Since it only happens some of the time, it's hard to calculate the impact, but based on a few days grappling with trying to debug and trigger this, it probably happens 5% or 10% of the time... And having 5%+ of customers lose their ability to advance through checkout is a major blocker to our ability to launch our new M2 site.

This bug impacts customer flow through checkout and is pretty serious. I hope this is going to be escalated and fixed VERY quickly. This is not a minor UI inconvenience to be fixed at some later date. This is a critical and inconsistent bug in the checkout...

If anyone has more information on what is actually causing this, or a workaround so I can hack something in there, I'd love more information. So far I haven't found anything more substantial than the above bug report.

@joshuaswarren
Copy link

FYI, the original bug report mentions this is impacting Magento CE 2.1. I can confirm this is impacting multiple Magento EE (Enterprise) 2.1.3 sites as well.

@reijervano
Copy link

The listener in Magento/Checkout/view/frontend/web/js/model/shipping-rate-service.js is called multiple times, because the quote.shippingAddress is changed (most of the fields are empty the second time, very strange). A workaround could by to block the execution of the function when some mandatory fields are not present of empty.

@wsagen
Copy link
Author

wsagen commented Feb 9, 2017

Any update on this? I've also noted that during page refresh the shipping-rate-service.js anonymous function is called twice.
Once it passes into setShippingRates.js setShippingRates, the radios become disabled after line
shippingRates(ratesData);
The ratesData contains the exact shipping rates both times this function is called, the second time the radios are disabled.

@ddeppner
Copy link

ddeppner commented Feb 17, 2017

Some observations:

The core issue here isn't that shipping methods become disabled, but that they don't become re-enabled. I don't have time to dig deeply into the architecture here or root causes. But I do need a quick fix so I can launch my M2 site and not wait for months until this bug fix gets fixed, with no feedback on an ETA.

So... I've tried to figure out an effective workaround in order to get my site launched without this critical bug that prevents checkout sometimes.

The code that disables the radio buttons is in the frontend in Magento_Ui/js/block-loader.js. That file is also the location of the code that is supposed to re-enable them. Check out the addBlockLoader() and removeBlockLoader() functions. addBlockLoader() disables any input or select elements in the hierarchy under the element that triggers the blockLoader, which in this case is the <li> with id of "opc-shipping_method" that contains all the methods and their radio buttons. The block loader is triggered via the data-bind attribute, specifically "blockLoader: isLoading". You can confirm this by just removing that so the block loader isn't triggered and the bug goes away (although you also don't get the spinning icon to indicate to the user that data is loading, so that's not a good fix).

When the block loader is invoked, it removes focus from any currently selected input field, makes them all disabled, and then sticks the loading icon over the top of the block being loaded. This is actually redundant, in a sense. You don't need to disable the input elements since they are now unselectable due to another element being on top of them.

I didn't mess around enough to understand why the removeBlockLoader() function can't seem to correctly remove the disabled property from input elements in some cases but not others. This may be due to the fact that the addBlockLoader() and removeBlockLoader() code is getting called twice some of the time, and it wasn't designed to be re-entrant. I.e., if you call addBlockLoader, then call it a second time, then call removeBlockLoader and then call it a second time, there definitely would be a logical problem with these functions that would trigger the bug. I didn't test enough to determine if that's what's actually happening or not. The mechanism there would be that on the first call to addBlockLoader, it's adding a "_disabled" class to save the state of any input elements that started out disabled, so later the removeBlockLoader call will only un-disable the elements that were not previously disabled. If you call addBlockLoader twice before a call to removeBlockLoader, the second addBlockLoader call would see that everything is disabled, mark everything with a "_disabled" class, and then none of them would be enabled after that by subsequent calls to removeBlockLoader. This is just speculation on one possible cause of the bug, though. I didn't check into it other than reading the code and confirming it should not be called twice. There may be a situation where it ends up being called twice in this manner (but only some of the time) due to variation in the timing of when various AJAX requests return. Note that since both of these functions work on all input elements under a parent object, this also means that the block loader should never be used on multiple blocks where one is the parent of another, or a bug like this could also be triggered. This could possibly impact other forms on other parts of the site? Again, just a theory. I don't know. Maybe there's something else going on.

Given that there is actually no point to disabling the elements because you can't select them while the loading icon is displayed anyway... The simple workaround is to comment out this line in block-loader.js:

//element.find('input, select').prop('disabled', true);

Since I'm not sure if that might have other unintended consequences on other pages, I opted to just wrap that in a conditional to prevent it from executing on this particular element in the checkout. So I think this is an effective workaround until this bug is fixed correctly... In addBlockLoader(), test for the id of the element being passed in, and if it's 'opc-shipping_method', skip disabling the radio buttons.

    if (element.attr('id') != 'opc-shipping_method') {
       element.find('input, select').prop('disabled', true);
    }

After implementing this on our staging site, we haven't experienced this bug in our testing.

Hope this helps...

@erikhansen
Copy link
Contributor

We are experiencing this on multiple Magento 2.1.x merchant sites.

Anyone who is interested in seeing a resolution on this issue: you should add a 👍 reaction to the original post in order for it to get more attention from the Magento team.

@royvanos
Copy link

royvanos commented Feb 24, 2017

@veloraven @SerhiyShkolyarenko any idea when this issue will be fixed? It's creating a lot of unnecessary confusion...

@AirmanAJK
Copy link

I just spent quite a bit of time debugging this one. It appears that whenever you have a postcode that will show up at checkout page load, either by a logged in user with a saved address, or a user who used the "estimate shipping" before moving to checkout, the call to update shipping rates is performed TWICE. Once to get the initial rate, but the second one seems to be due to the postcode getting filled out at page load, triggering a knockout binding event 2000 milliseconds after it's updated.

In any case, the radio buttons get disabled at Magento_Checkout/js/model/shipping-service.js once the setShippingRates function calls the line "shippingRates(ratesData)" a second time. It looks like knockout is toggling the disabled status (though I can't find where), because once I step over that line, the radio buttons become disabled and stay that way. I believe it is toggling because the first time it is called the radio buttons go from disabled to enabled, and the second call 2 seconds later does the opposite.

My hack fix is to add the following line at the end of the setShippingRates(rates) function:
jQuery(".table-checkout-shipping-method input[type=radio]").prop("disabled", false);

I realize that this is not a good fix, and the true reason they are being disabled should be addressed, but as the commenters in this thead have said, this is a store breaking bug that will cause customers to leave.

I hope this helps someone willing to take over the debugging.

@reijervano
Copy link

@vrann Hello Eugene, were you guys able to frix this on the Hackaton?

@vherasymenko
Copy link

vherasymenko commented Apr 26, 2017

On latest 2.1-develop version another issue.
Radio buttons are disappears after refresh page using (CTRL + R )

@Turv
Copy link

Turv commented Apr 26, 2017

Still an issue 5 months on.. do we have a legitimate work around?

@ddeppner
Copy link

@Turv My Feb 17 comment above is a successful workaround that we're using on our live site, at least until this is fixed properly.

@deepakkn85
Copy link

I will start looking this issue.

magento-team pushed a commit that referenced this issue Jul 28, 2017
…ady giving out a "validation failed" error at page load - for 2.1

MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
magento-team pushed a commit that referenced this issue Jul 28, 2017
… UPS #6564 - for 2.1

- MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
magento-team pushed a commit that referenced this issue Jul 28, 2017
… UPS #6564 - for 2.1

- MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
magento-team pushed a commit that referenced this issue Jul 28, 2017
…ing address during checkout they are unable to place the order - for 2.1

- MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
magento-team pushed a commit that referenced this issue Jul 28, 2017
… UPS #6564 - for 2.1

- MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
magento-team pushed a commit that referenced this issue Jul 28, 2017
… UPS #6564 - for 2.1

- MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
magento-team pushed a commit that referenced this issue Jul 28, 2017
…ing address during checkout they are unable to place the order - for 2.1

- MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
magento-team pushed a commit that referenced this issue Jul 28, 2017
…ing address during checkout they are unable to place the order - for 2.1

- MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
magento-team pushed a commit that referenced this issue Jul 28, 2017
…ing address during checkout they are unable to place the order - for 2.1

- MAGETWO-70727: [GitHub] Shipping method randomly dissapear when page refreshed for 2.1 #7497
@vzabaznov
Copy link
Contributor

Hi @wsagen MAGETWO-70727 issue was fixed and will be delivered in 2.1.8 release, sorry to all for such delay, please let me know if your issue was fixed and feel free to write here or reopen if still have this issue

@magento-team
Copy link
Contributor

Internal ticket to track issue progress: MAGETWO-68875

@korostii
Copy link
Contributor

korostii commented Aug 1, 2017

Hi @vzabaznov,
2.1.8 is not even released yet. Did you by any chance mean "please test whether the issue is reproducible for you when using the source code taken from branch 2.1.8-preview using the clone from repository method of installation" ? Otherwise it's quite misleading,

Please don't close the issue as long as the fix isn't in any of the releases yet. It's utterly confusing.
Please consider using the GitHub's "Milestones" feature instead.

@nghitrum
Copy link

Still, have this problem in 2.2.5.

@nbennett25
Copy link

nbennett25 commented Nov 8, 2018

Also having the same issue in 2.2.5 - can we get this ticket re-opened?

@mariuszjeruzal
Copy link

Problem exists 2.2.6

@Nastradoomus
Copy link

Nastradoomus commented Jan 31, 2019

Just heard a compaint from a customer who could not proceed to check out due to the fact that shipping methods with a price stays hidden after adding post code. I can't reproduce this error and debug it. Can someone verify the steps that led to the problem?

Free shipping methods are open.

2.2.6

@jeffekg
Copy link

jeffekg commented Jul 25, 2019

Getting this on 2.3.2 EE

Edit: This was caused by the B2B modules. After removing them, issue went away.

@emanuelerangan
Copy link

emanuelerangan commented Jul 26, 2019

Magento 2.3.2 CE also affected by this problem, here's my workaround:

  • inside my theme version of vendor/magento/module-checkout/view/frontend/web/js/model/shipping-service.js
  • inside setShippingRates function, last thing:

setShippingRates: function (ratesData) {
shippingRates(ratesData);
shippingRates.valueHasMutated();
checkoutDataResolver.resolveShippingRates(ratesData);

setTimeout(function() {
	var container = document.getElementById('co-shipping-method-form');
	if (container) {
		var inputs = container.getElementsByTagName('input');

		ratesData.forEach(function(rate) {
			if (rate.available) {
				var name = rate.carrier_code + '_' + rate.method_code;
				for (var i = 0; i < inputs.length; i++) {
					if (inputs[i].value === name) {
						inputs[i].removeAttribute('disabled');
					}
				}
			}
		});
	}
}, 1000);

})

@marcosdsdba
Copy link

This problem in 2.3.1 too.

@josiahglassone
Copy link

I also have this problem in v2.3.1

@cannycookie
Copy link

Still an issue in 2.3.3. @devs to replicate we have to enable bandwidth throttling to simulate slow connections. On the cart If you re-edit the postcode WHILST the subtotals are still calculating then the radios stayed disabled.

@daniel-berko-work
Copy link

daniel-berko-work commented Nov 25, 2019

I can second that the issue remains on 2.3.3 CE.

@andresams
Copy link

andresams commented Apr 10, 2020

I was able to successfully reproduce the issue on Magento 2.3.4 and create a real fix for it.

How to reproduce the error

  1. Create a new account without an address
  2. Add a product to the cart
  3. Go to the shopping cart page and make sure the "State" field is NOT selected
  4. Enter a postcode and wait until the shipping rates are loaded
  5. Change the last digit of the postcode to another number and repeat this operation multiple times, quickly enough to trigger the shipping rates calculator multiple times.

After a few times, you will see that the radio fields will not get re-enabled.

What is really happening?

In order to understand what really happens, please, look at this code snippet:

vendor/magento/module-checkout/view/frontend/web/js/model/shipping-rate-processor/new-address.js

            storage.post(
                serviceUrl, payload, false
            ).done(function (result) {
                rateRegistry.set(address.getCacheKey(), result);
                shippingService.setShippingRates(result);
            }).fail(function (response) {
                shippingService.setShippingRates([]);
                errorProcessor.process(response);
            }).always(function () {
                shippingService.isLoading(false);
            });

When we successfully receive the results from the POST request, we are using shippingService.setShippingRates() to send the new data to a knockout observable, which then triggers the updates to the HTML. However, right after this function runs, we also run the "always" callback, which is responsible for removing the block loader and re-enabling the radio fields (they got disabled when we ran shippingService.isLoading(true), which displays the block loader). The problem here is that there is a small delay of a few milliseconds between the time the observable is notified and when the HTML is in fact updated, so we end up running shippingService.isLoading(true) BEFORE the new HTML is rendered, causing a scenario where the radio fields never get re-enabled.

How to fix it

All we have to do is to add a delay of a few milliseconds to this function, to make sure that the new data is rendered when we remove the blocker and try to re-enable the form fields:

vendor/magento/module-ui/view/base/web/js/block-loader.js

function removeBlockLoader(element) {
    setTimeout(function() {
        if (!element.has(blockLoaderClass).length) {
            return;
        }
        element.find(blockLoaderClass).remove();
        element.find('input:not("._disabled"), select:not("._disabled")').prop('disabled', false);
        element.find('input:disabled, select:disabled').removeClass('_disabled');
        element.removeClass(blockContentLoadingClass);
    }, 500);
}

This will fix the issue in all locations where the block loader is used, including the cart and checkout pages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report Component: Checkout Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development
Projects
None yet
Development

No branches or pull requests