Suggested new implementation of ComponentPropertyModel
------------------------------------------------------
Key: WICKET-2119
URL: https://issues.apache.org/jira/browse/WICKET-2119
Project: Wicket
Issue Type: Improvement
Components: wicket
Affects Versions: 1.3.5
Reporter: Willis Blackburn
I would like to propose a replacement for ComponentPropertyModel.
The existing version addresses a specific situation: How to use
CompoundPropertyModel with a child component that requires two models?
However, I think that the existing implementation has some issues:
1. It doesn't actually behave like the model-finding logic of Component.
Component searches up the component hierarchy until it finds a component with a
model that implements IComponentInheritedModel. ComponentPropertyModel just
uses the parent component's model. So if, for example, a Page with a
CompoundPropertyModel contains a model-less Form, and the Form contains
model-less fields, then the fields will find the Page model, but any
ComponentPropertyModels will try to access the Form model.
2. ComponentPropertyModel can *only* use a property of the parent's model and
not the parent's model itself.
3. It implements IComponentAssignedModel, which is confusing for Wicket
beginners. Sometimes IComponentAssignedModel is unavoidable, but in this case,
the component is only needed in order to access its parent, which is an issue
in itself (issue 1). In almost all cases, the parent of a Component using
ComponentPropertyModel is already known, so why not just pass it to
ComponentPropertyModel directly?
My proposed implementation accepts a Component and delegates operations to that
Component's model. It also optionally allows an expression for accessing a
specific property of the target Component's model. This addresses a very
common use case: A Component needing to use the model of some other Component
directly. As an example, AjaxEditableLabel creates two components that both
use AjaxEditableLabel's model.
Having a component that directly uses the model of some other component is
difficult with existing model implementations. The obvious way to do it is to
call getModel on the parent component, then use the returned model in the child
components, either directly or in combination with PropertyModel. There are
two gotchas with this approach:
First, the model of the parent component may not be known in the parent
constructor: The parent may not have a model and may expect to get its model
from an IComponentInheritedModel higher in the component hierarchy, however the
parent has not yet been added to *its* parent in the constructor, and so the
inherited model is not yet available. Therefore, a Component that wants to
create children that use its own model cannot create those children it in its
constructor. It must lazily create them in the onBeforeRender method instead.
Second, and more generally, an application can call setModel on the component
at any time. If the component passes its model to its children, then it also
has to intercept setModel and reset the child models. AjaxEditableLabel does
this, but it only has two child components to manage.
A strategy for child components that want to use their parent's model is to
create a PropertyModel in which the target object is the Component containing
the actual model and the property expression starts with "modelObject."
Basically, my proposed ComponentPropertyModel implements this functionality,
except that the "modelObject" part of the expression is implied. For this
particular use case, it is clearer and a bit more efficient than new
PropertyModel(someComponent, "modelObject.property.expression").
Using this model, AjaxEditableLabel would become much simpler. It could create
the child Label and TextField components once, in the constructor, passing new
ComponentPropertyModel(this), and not have to worry about onBeforeRender or
setModel.
Let me know what you think.
I wrote a test case for this, but I can't actually run it due to the issue with
the component instantiation listener that Application installs; see my other
jIRA issue about this.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.