Overriding/alternative to t:id when building composite sub-form components
--------------------------------------------------------------------------
Key: TAPESTRY-2350
URL: https://issues.apache.org/jira/browse/TAPESTRY-2350
Project: Tapestry
Issue Type: Improvement
Components: Core Components
Affects Versions: 5.0.11, 5.0.12
Reporter: Philip Lopez
It does not appear to be possible to specify the t:id value through more than
one layer of a component hierarchy. This becomes a problem when trying to build
reusable form widgets, particularly as the validation infrastructure uses the
component's t:id as the key into configuration (via properties), e.g. for
regexp.
Here is an example of what I'm trying to do -- the motivation being to build a
set of reusable form building blocks for a large number of corporate developers
(and many separate systems), the goal being to encapsulate markup/CSS standards
into a library... effectively a simple DSL.
Imagine a set of "Question" widgets, e.g. a QuestionText that has something
like the following TML:
<div>
<t:label class="question" for="textQuestion" />
<t:textfield t:id="textQuestion" ... />
<t:if test="required"> <em>*</em> </t:if>
</div>
Using this widget we can write simply:
<div t:type="QuestionText" t:id="accreditationCode"
validate="required,regexp" />
rather than the full set of markup for each question, and we've encapsulated
non-semantic markup such as the wrapping div, the order of label and field, the
presence of a mandatory field marker (*) and css classes. Component frameworks
are ideal...
BUT... because we have to set the t:id="textQuestion" in this QuestionText
component (e.g. for label to work, and because t:id cannot be bound to a
parameter/expression), when we drill into using Tapestry's sophisticated
features, life becomes hard.
We can reproduce the automatic "value" -> "id" transformation that Tapestry
does for TextField by reproducing AbstractTextField.defaultValue() in our
QuestionText component. Similarly, we can pass through validators by injecting
FieldValidatorSource. It's a little painful, but worth the effort (for my use
case). Using clientId is necessary also, to build nice, testable (e.g.
WebDriver) markup -- although perhaps that will break in larger/iterated
composites.
But since FIeldValidatorSourceImpl uses ComponentResources.getId() to lookup
constraints and messages in the Messages "context", it does not appear possible
(at least to me) to easily override this behaviour.
Being able to programmatically override t:id might break the static structure /
dynamic behaviour model, but I'm wondering whether t:id is doing double-duty
here, and perhaps there needs to be another abstraction for id (~ controlName,
~clientId) that <em>can</em> be injected across multiple layers of components
-- perhaps defaulting to t:id otherwise... but that would seem to need another
entity such as t:logicalId, with all the required changes back up to the
template parser...
AFAIK, Field.controlName or ClientElement.clientId are a little too "generated"
for uniqueness reasons.
I'm not sure if mixins can be used here, but I'd rather use the existing
Tapestry validation framework than implement a parallel one. Perhaps a less
obvious approach, but maybe more elegant, is to look at decorating standard
Field components.
In summary... does t:id have to be overridden to build up reusable (larger)
form widgets, or are there some more feasible alternatives?
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]