The method always enforces a rebuild when the selected payment method doesn't match, at least when not using Javascript. Can't reproduce it with javascript.
Even if there is only a single payment method to be selected, so at least that might be something to optimize?
Testing this with an automated test, I have to press "Pay" twice, and there is no visual feedback the first time. Might be related to an earlier issue that we've opened.
Comments
Comment #1
xanoThe idea is that you click Choose payment method first, which shows you the form to configure the payment using that payment method. This includes fields, and the payment method plugin's configuration form. It's hard, if not impossible, to know whether any form elements are to be displayed beforehand. Using JavaScript we can make this workflow much more user-friendly, but we still have to make a request to the server to check for possible form elements to display. What visual feedback would you like to see?
Comment #2
xanoBump.
Comment #3
xanoClosing due to lack of feedback. Feel free to re-open the issue if you think #1 is incorrect of if you have additional relevant information.
Comment #4
berdirI re-found this bug the second time now, without knowing it at first, only remembered it now.
The problem is the $form_state->setRebuild(). I can't say how to fix it, but calling setRebuild() inside a validate callback is doing weird things, in my case, it was breaking ajax submits in weird ways, because it would no longer call my submit callback.
Can't show that form right now, but it works like this:
Multiple radio elements with different options to buy, different prices:
* Option 1 (1 $)
* Option 2 (100 $)
Users have a balance, so I don't always show the payment form. Assuming the user has a balance of 5 and Option 1 is selected by default, he doesn't see a payment form. Then he does this:
1. Click on Option 2, ajax updates and displays the payment form.
2. Click back on Option 1, the payment form is still visible. This is because this is the first submit with the payment form, it goes into that if(), which means it skips my submit and rebuilds the form as-is instead.
As mentioned above, the same happened in our tests when we had more than one payment form, then we had to do drupalFormPost() twice for "Pay".
I'm not sure how, but this case should not be triggered, as the payment method did not change, it is the initial default value, which is however not yet set as selectedPaymentMethod(), IIRC. So the fix might be to default the selectedPaymentMethod to the first one?
Comment #5
xano#2452611: Convert payment method selectors to reusable plugin selectors will impact this.
Comment #6
xanoTheoretically triggering a rebuild during validation should work, right? That's exactly what form API's validation does itself. Any rebuild should also prevent submit handlers from being invoked.
I tried to reproduce this problem by hand and I *think* (part of) the issue is that any payment method that extends
\Drupal\payment\Plugin\Payment\Method\PaymentMethodBasealso implementsPluginFormInterfaceand the selector therefore rebuilds the form when such a method is chosen.Comment #7
xanoWhen using the selectors that ship with Payment and setting them as required, I do not get any initial values. How did you end up getting them?
Comment #8
xanoDoes this still happen?