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]

Reply via email to