Hi,
Using a FormComponentPanel with Ajax is quite cumbersome from the client
perspective: you have to add Ajax behavior to its nested components. And if a
panel has more than 1 nested components, you need to add multiple behaviors.
Combining the values of the nested components in the behaviors is also
cumbersome. It would be nice if you could add an Ajax behavior to the panel,
and simply be able to access the model object of the panel in the behavior.
I figured out a way to be able to add a AjaxFormComponentUpdatingBehavior to a
FormComponentPanel, and in onUpdate(...) have an up-to-date model of the panel.
If you add the following to the Multiply example, convertInput() of Multiply
will see the correct values for the converted inputs of the nested form
components:
@Override
public void validate() {
processInputIfNeeded(lhs);
processInputIfNeeded(rhs);
super.validate();
}
private void processInputIfNeeded(FormComponent<?> nestedComponent) {
if (nestedComponent instanceof FormComponentPanel<?> ||
!Objects.equals(nestedComponent.getInput(), nestedComponent.getRawInput())) {
nestedComponent.processInput();
}
}
But for this to work properly, recursive serialization must be enabled for the
attributes of the behavior. Otherwise the data of the nested components is not
sent to the server. So a client adding this behavior must make sure to do this
by overriding updateAjaxAttributes. As this is error-prone (and not how you use
the behavior with other form components), I figured I could solve it with an
AjaxRequestTarget.IListener.
Here I run into a problem: the method to get the component of an Ajax behavior
is not public. If the method was public, I can see the following solution to
easily allow Ajax updates for FormComponentPanels:
* Extension of FormComponentPanel with processInputIfNeeded(...), so sub
classes do not have to copy this logic.
* Addition of a flag (which is not set by default) to FormComponentPanel,
telling the listener that recursive serialization must be enabled for
AjaxFormComponentUpdatingBehaviors attached to the panel.
* An AjaxRequestTarget.IListener implementation that will enable recursive
serialization if the behavior is a AjaxFormComponentUpdatingBehavior and the
FormComponentPanel has the flag set.
Creating and using FormComponentPanels that can be used with Ajax updates is
then possible by:
* Adding a listener to the application.
* Setting the flag on a panel.
* Overriding validate() and invoking processInputIfNeeded(...) for each nested
component.
The only issue with this approach I found so far is that processInput() will be
called on nested FormComponentPanels in situations where it is not needed.
So my questions are:
* Is there a reason to not expose the component of an Ajax behavior?
* Will my approach break in some situations? Result in unnecessary expensive
processing? ...
Thanks in advance for your answers.
--
Best regards / Met vriendelijke groet,
Johan Stuyts
Squins IT Solutions BV
Oranjestraat 30
2983 HS Ridderkerk
The Netherlands
www.squins.com
Chamber of commerce Rotterdam: 24435103
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]