Reviewed & tested by the community
Project:
Commerce Ajax Add to Cart
Version:
8.x-1.x-dev
Component:
Code
Priority:
Critical
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
2 Feb 2018 at 10:30 UTC
Updated:
10 Sep 2021 at 15:30 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
subhojit777Do you mean:
Comment #3
Yiannis.Tzikas.Ziogos commentedOf the same product. So when I add the first one everything is ok. When I add the second one (different of first), variation is added to the cart. But when I try to add a third variation of the same product, the second one is replaced by the third one. And so on...
Comment #4
l_v commentedHi, I've same issue.
Comment #5
l_v commentedHi, I think is something connected with form id changed by the module via ajax.
Here's my use case:
- when pages are refreshed via http change you can add as many variations as you like
- when you change product variation via ajax you can add only one variation, each time you try to add another variation the system remove the last added.
This is the case:
- view product
- add variation to cart (you can add as many variation of this type as you like)
- change variation via ajax
- add this variation (you can add as many variation of this type as you like)
- change variation via ajax
- add this variation: the system replace the last one with this
If you refresh the page you can restart from the first step
Comment #6
l_v commentedComment #7
mglamanThe best way to debug this is to write a FunctionalJavascript test to reproduce the bug.
Comment #8
subhojit777Thanks Matt. I will whip up some tests.
By the way. After debugging I found that during the third time it is not creating a new order item. But using the last (second) one. And it gives the sense that the lastly added item is replacing the second last one -- which is the bug.
Comment #9
l_v commentedHi subhojit777, thanks for your suggestion.
As you noticed the problem is linked with new order items. It seems that changing the form via ajax, in some way, doesn't reset the order_item_id and the order item uuid.
At the moment I've done a dirty trick. I override in your module the submitForm method and reset inside of it the keys.
This my dirty code (in AjaxAddToCartForm.php):
Sorry, but I'm not a debugger and I'm not able to create patches.
I hope my code can be usefull and you can resolve the bug asap, your module is great! And I need it for a project of mine ;-)
Comment #10
subhojit777Not a problem at all. Thanks for the effort.
Comment #11
subhojit777Comment #12
subhojit777Added the tests https://github.com/subhojit777/dc_ajax_add_cart/commit/5cf062b42baaded36...
Comment #13
subhojit777@l_v If this is blocking your project you can upload a patch of the code in #9 and then use the patch using composer-patches. Since this is a workaround so it won't be committed to the module. I am looking for the core problem. Commits will be made after identifying the core problem.
Comment #14
subhojit777After more debugging I figured that the reason that new order item is not being created is because the form build id is not getting refreshed. Although, as per the code
RefreshPageElementsHelper::updateFormBuildId()should be called every time a product is added to cart, but it looks like it is using the stale build id - when the variation is changed the second time. I am not sure why it is happening only the second time. I think I have to dig into the variation switcher as well. Maybe it is not refreshing the add to cart form build id - which it should - and it relies on the page reload to get the new build id, and it fails when the add to cart form button is ajaxed. I will ask Bojan again for some hints.Comment #15
subhojit777The reason behind the bug occuring the second time because the ajax add to cart form build id is updated successfully only once, after a variation is added to cart for the first time. In subsequent requests, the build id is not updated, i.e.
RefreshPageElementsHelper::updateFormBuildId()is not called.Comment #16
subhojit777I added this inside
ProductVariationWidgetBase::ajaxRefresh()but it is still not working.RefreshPageElementsHelper::updateFormBuildId()is not getting called either the second time.Comment #17
subhojit777I tried fixing this using
commerce_product.variation_field_renderer'sreplaceRenderedFields(), but no.. still not working. I am running out of ideas here. But I am quite sure that this is happening due to stale form build ids.Comment #18
subhojit777Actually. I am not entirely sure on that. To prove my assumption, I had put a
UpdateBuildIdCommand()insideProductVariationWidgetBase::ajaxRefresh(), after the event dispatcher - but it didn't work.Comment #19
abrammI have a custom AJAX cart module which I made before dc_ajax_add_cart for D8 was released and I'm having exactly the same problem.
The problem is caused by the way Add to Cart form works.
It was not intended to be submitted multiple times; thus, it's not AJAX compatible by it's nature.
The AddToCartForm class inherits ContentEntityForm class which stores entity object (order item in our case) as a property.
Drupal serializes form_state while saving form cache and so it stores AddToCartForm object instance with existing order item entity inside.
As a workaround, I've added the following submit callback to a submit button:
This is not a correct way to fix this issue (since that's just a hack which replaces stored object), however, adding to cart will work.
Comment #20
mschudders commentedI've rolled #9 into a patch.
Can confirm this resolves the issue.
See attached
Comment #21
abrammI didn't post #19 as a patch since it's not a correct way to fix an issue. Please remember it's a hack.
Comment #22
xamountI am having the same issue. Patch at #20 solved my problem. I'm currently using this patch and I am able to successfully add different variations of the same product via the ajax add to cart button.
Comment #23
imclean commentedSee #21.
Comment #24
xamountThe patch at comment #20 comes from #9 not #19. Please read carefully.
Comment #25
brianwagner commentedSimilar to #19, I'm facing this issue with custom ajax functionality. I agree with the assessment about the stale entity that is associated with the form. And that goes back to how AddToCart form works, as it's not built for ajax (in the way commerce panes are for example). My sense is that a more durable solution is to rebuild/refresh the form as part of the ajax operation. That would refresh the build_id or replace the associated entity. I'm not sure what is required to achieve that exactly. But it seems @subhojit777 was trying to find a fix in that direction.
If anyone can provide guidance on how that is done with ContentEntityForm or another, I would be happy to work on it.
Comment #26
dubs commentedThe patch at #20 works for me - thank you for submitting
Comment #27
steven jones commentedMy colleague posted a fix for this to commerce over in #3232344: Make it easier to ajax submit the default cart form, do not re-use order items since you can run into this problem if you make the add to cart form submit using ajax not using this module.
It's a simple two line fix for commerce, or it could be incorporated here in the middle of the code in #20 rather than the uuid specific code that's there at the moment if desired.