I could not use the patch, because the code it is altering is in a piece of final Wicket code and I am not allowed to (or willing) to use a custom Wicket version that was built from sources by ourselves.
So I had a look at the workaround. The instructions for using it are a bit vague... Should we modify the nested form (the one inside the modal window) or the root form (the one on the page itself)? I am not sure. I initially tried with the nested form but the change broke my whole environment. Somewhere it is trying to set the default submit button by calling setDeafultButton, but that method then goed into an infinite loop. It's code calls both isRootForm() and getRootForm(), but in the sugested workaround we override getRootForm in a way that makes it inconsistent with isRootForm. If getRootForm returns this, than isRootForm on this should return true... I altered it so that that is indeed true, and that made it work sorta, but the issue was not fixed by it...
So I dug deeper and then found a (the) solution.
First some observations:
1) Wicket supports nested forms, but HTML does not. To deal with that, Wicket renders divs instead of forms for any nested forms
2) Wicket's ModalWindow component renders a form tag all of it's own, which looks like this:
<form style="background-color:transparent;padding:0px;margin:0px;border-width:0px;position:static"><!-- all modal window content is in here, including the nested form DIV --></form>
3) Wicket's docs state that the modal window should be inside a Form to prevent nested forms from giving issues:
"If you want to use form in modal window component make sure that you put the modal window itself in another form (nesting forms is legal in Wicket) and that the form on modal window is submitted before the window get closed."
If you don't do this the way the docs prescribe, you may get hit by issues such as
4) When you do nest the whole modal window inside a Wicket Form, like this:
<form wicket:id="modalForm" class="modalForm">
<div id="ajax-indicator" class="ajax-indicator">...</div>
You will get HTML that looks like this:
<form class="modalForm" ... ></form>
<!-- modal window content -->
<div class="modalwindow" id="form4fa5">
<input type="button" onclick="var wcall=wicketSubmitFormById('buttonForm4fa5', ..."/>
Surprisingly, in the HTML the modal window is not nested inside, but positioned side by side with the modalForm.
The button's onclick does a wicketSubmitFormById, passing the id of the nested form (which is rendered as a div).
The implementation of wicketSubmitFormById grabs the div with id "form4fa5" and from there on looks up in the element tree until it finds a form element. It finds the <form style="background-color:transparent;..."> that was rendered by the modal window component. It then grabs all inputs from this form and submits them with an ajax post.
5) On the server side, the post request is being handled by a Wicket behavior named AjaxFormSubmitBehavior.
(I am not sure whether this is the only way to do it with ajax, but this is how we are doing it)
6) That behavior calls onFormSubmitted() on the root form, which calls inputChanged on all it's form components, which try to find their input in the request but fail because only the form generated by the modalwindow component was ever submitted. This is the final cause of this issue.
Which brings me to the workaround.
I can't see how the root form can ever get submitted when it is not the same as the nested form, so it seems unreasonable to fire the onFormSubmitted method on it. So I extended AjaxFormSubmitBehavior and made an override for onEvent (which thankfully was not final. Thank you!!) that only calls onFormSubmitted on the nested form. So I just replaced it's first line:
This fixes my issue and I don't see any side-effects.
Hopefully this will help you guys fix form handling for nested forms in dialogs, because it seems it's still broken in Wicket 1.5 as well (don't know about Wicket 6).
WICKET-3404: Improve ModalWindow form handling
Fwd: wicket nested form and modal