Closed wsagen closed 7 years ago
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.
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
Reproduced. Created internal issue MAGETWO-61384. Thank you!
Any fix for this issue?
@Tapin1 issue is in queue for fixing. We don't have estimates yet.
We too are experiencing this issue on Magento 2.1.2 and can reproduce the problem with the following steps:
The radio buttons will then all disable after a few seconds although the radio button labels remain clickable.
I have upgrade magento with latest 2.1.3 and still this issue is present.
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.
Has anyone a fix for this?
Actually the problem disappeared when I updated all my extensions.
This problem is still there in the latest version!
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.
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.
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.
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.
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...
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.
@veloraven @SerhiyShkolyarenko any idea when this issue will be fixed? It's creating a lot of unnecessary confusion...
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.
@vrann Hello Eugene, were you guys able to frix this on the Hackaton?
On latest 2.1-develop version another issue. Radio buttons are disappears after refresh page using (CTRL + R )
Still an issue 5 months on.. do we have a legitimate work around?
@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.
I will start looking this issue.
Hi @wsagen, i'm sorry for such delay, bug that @K7Triton described confirmed, https://jira.corp.magento.com/browse/MAGETWO-70465 was created to fix all further problems in complex
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
Internal ticket to track issue progress: MAGETWO-68875
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.
Still, have this problem in 2.2.5.
Also having the same issue in 2.2.5 - can we get this ticket re-opened?
Problem exists 2.2.6
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
Getting this on 2.3.2 EE
Edit: This was caused by the B2B modules. After removing them, issue went away.
Magento 2.3.2 CE also affected by this problem, here's my workaround:
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);
})
This problem in 2.3.1 too.
I also have this problem in v2.3.1
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.
I can second that the issue remains on 2.3.3 CE.
I was able to successfully reproduce the issue on Magento 2.3.4 and create a real fix for it.
After a few times, you will see that the radio fields will not get re-enabled.
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.
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.
Preconditions
Steps to reproduce
Expected result
Actual result
We've also observed this on initial checkout page load but not able to provide instructions to reliably reproduce this every time.