[ 
https://issues.apache.org/jira/browse/TAPESTRY-2350?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12595996#action_12595996
 ] 

Philip Lopez commented on TAPESTRY-2350:
----------------------------------------

In case anyone has a similar need, here's a simple alternative approach that 
seems to be working. It's a little more verbose, and not as flexible, but also 
avoids a duplicate component hierarchy problem.

Haven't had a chance yet to follow on through the BeanEditor idea (although I 
did borrow some of those techniques for something else), but I did come up with 
a simpler approach to overriding the element IDs, that doesn't violate 
encapsulation.

The solution I used was a "QuestionTemplate" component that is simpler and will 
work most of the time. The only real ugliness is the duplication of the "for" 
element...

QuestionTemplate.tml:

<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
    <div class="question">
        <t:label t:id="label" class="prompt" for="prop:field" />

        <t:body />

        <t:if test="required">
            <span class="requiredIndicator">*</span>
        </t:if>
    </div>
</t:container>


QuestionTemplate.java:

public class QuestionTemplate
{
    @Parameter(name = "for", required = true, defaultPrefix = "component")
    private Field field;

    public Field getField()
    {
        return field;
    }

    public boolean isRequired()
    {
        return field.isRequired();
    }

}



Example usage:

<div t:type="form/QuestionTemplate" for="eCode">
    <t:textfield t:id="eCode" validate="required,regexp" />
</div>



> 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
>            Assignee: Howard M. Lewis Ship
>
> 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