> On 16 Jul 2015, at 22:00, Nicolas Le Bas <[email protected]> wrote: > > I see. > So basically you like to use tiles as some kind of Domain Specific > Langage for your views. > > What if we add support for something like raw data for an attribute, > that would be translated into a Map for rendering? > > Something like: > <definition name="customers/info" extends="customers/base"> > <put-list-attribute name="body" cascade="true" inherit="true"> > <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" /> > </put-list-attribute> > <put-xml-attribute name="breadcrumbs" cascade="true" inherit="true"> > <breadcrumbs> > <link href="/customers/${customer.id}">${customer.id}</link> > <link href="/customers/${customer.id}/salesOrders">Orders</link> > <link > href="/customers/${customer.id}/salesOrders/${order.id}">${order.id}</link> > </breadcrumbs> > </put-xml-attribute> > </definition> > > I think most of the pieces to support it are already there: > - we already have support for evaluating the expressions at runtime. > - we can find libraries out there that translate XML into a usable map > structure (xstream?) > > The only thing that worries me is whether the good old digester would > accept to release control of the parsing and let us access the whole > body of put-xml-attribute, or if we would have to rewrite > DigesterDefinitionsReader. I'm not sure there. > > How does that sound? What do you think?
It's certainly a flexible approach that could prove useful, I am ok with the add-list-attribute mck suggested which works as advertised, I made pull request #5 (https://github.com/apache/tiles/pull/5) which adds expression support to list attributes, mck made some requests before accepting but the logic I think is sound. Btw, the example I submitted works in the current release of tiles withe the exception of expression evaluation which #5 addresses. All in all we can probably close this pull request and concentrate instead on #5. > Nick. > >> On 15-07-14 10:18 PM, Brett Ryan wrote: >> >>> On 15 Jul 2015, at 11:53, Nicolas Le Bas <[email protected]> wrote: >>> >>> Hi all, >>> >>> First of all, I take responsibility for cross posting to the dev list. >>> Sorry if it surprised you, Brett, I just feel it is a better place to >>> discuss code changes. People come here with a different mindset. >> >> My bad actually, I should have realised there was a dev@ list, I subscribed >> to users@ years ago and didn't bother to check when submitting patches. >> >>> And sorry for the delay in my answer, too. We're all volunteers here :) >>> As a consequence, it will be a long answer, and I feel like apologizing >>> again. >> >> Hah, it's cool :) I've been unwell and unable to finalise a solution to >> mck's requests, I was hoping to resume on the weekend but have been >> bed-ridden and can't think properly. It happens, what ya gonna do? >> >>> Concerning a universal solution to Brett's problem: well, here's what >>> I've been doing for the past years. I do not pretend it is better, just >>> that I like it: >>> >>> >>> I find, like Brett, that the "JavaBeans" tags from struts-tiles (item >>> and bean) are limited in nature. In my experience I only encountered two >>> situtations were they were useful, and in both situations I've found >>> other solutions to be more effective and maintainable. >>> >>> >>> 1. The static approach >>> I like the pure HTML+CSS solution to this: <ul><li>My Account</li><li>My >>> Orders</li></ul>. It looks and lives well within the template itself. >>> >>> 2. The dynamic list. >>> In most cases, I find it more convenient to add a bean into the >>> appropriate context through the application. For instance, with spring: >>> >>> <util:list id="breadcrumbsData"> >>> <bean class="example.Link" p:value="#{customer.id}" >>> p:link="/customers/#{customer.id}" /> >>> <bean class="example.Link" p:value="Orders" >>> p:link="/customers/#{customer.id}/salesOrders" /> >>> <bean class="example.Link" p:value="#{order.id}" >>> p:link="/customers/#{customer.id}/salesOrders/#{order.id}" /> >>> </util:list> >>> >>> And then in tiles: >>> <put-attribute name="breadcrumbs" expression="${breadcrumbsData}"/> >>> >>> I find this "breadcrumbsData" tends to evolve over the life of the >>> application into something more and more dynamic, for instance session >>> specific or requires a data model more complex than the <item>-type of >>> thing. Sometimes it is also more convenient to create the list by hand >>> and add it to the session/servlet context programatically. >> >> I'm trying to remove things like this as much as possible from the >> application context and defer to tiles as it's a lot less work. Consider >> this in my template: >> >> <tiles:importAttribute name="breadcrumbs" ignore="true"/> >> <ol class="breadcrumb"> >> <c:forEach var="item" items="${breadcrumbs}" varStatus="vs"> >> <li class="${vs.last ? 'active' : ''}"> >> <c:choose> >> <c:when test="${vs.last}"> >> <c:out value="${item[0]}"/> >> </c:when> >> <c:otherwise> >> <a href="<c:url value="${item[1]}"/>"><c:out >> value="${item[0]}"/></a> >> </c:otherwise> >> </c:choose> >> </li> >> </c:forEach> >> </ol> >> >> Now with this I can opt-in to providing crumbs in many different views, >> which can be completely dynamic and inheritable by tiles. Consider the >> customers crumbs I've been using, note that this has been changed from using >> the "<item/>" version to using nested <add-attribute/> values, though I've >> raised a new pull-request that I need to alter which provides expression >> support as it's not presently available. >> >> <definition name="customers/base" extends="customers/none"> >> <put-attribute name="title" cascade="true" >> expression="${customer.sortName} (${customer.id})" /> >> <put-list-attribute name="body" cascade="true"> >> <add-attribute value="/WEB-INF/views/customers/menu-tabs.jsp"/> >> </put-list-attribute> >> <put-list-attribute name="breadcrumbs" cascade="true" inherit="true"> >> <add-list-attribute> >> <add-attribute value="Customers"/> >> <add-attribute value="/customers"/> >> </add-list-attribute> >> </put-list-attribute> >> </definition> >> >> <definition name="customers/info" extends="customers/base"> >> <put-list-attribute name="body" cascade="true" inherit="true"> >> <add-attribute value="/WEB-INF/views/customers/cust-info.jsp" /> >> </put-list-attribute> >> <put-list-attribute name="breadcrumbs" cascade="true" inherit="true"> >> <add-list-attribute> >> <add-attribute expression="${customer.id}"/> >> <add-attribute >> expression="/customers/${customer.country}/${customer.id}/info"/> >> </add-list-attribute> >> </put-list-attribute> >> </definition> >> >> <definition name="orders/view" extends="customers/base"> >> <put-list-attribute name="body" cascade="true" inherit="true"> >> <add-attribute value="/WEB-INF/views/customers/cust-salesOrder.jsp" /> >> </put-list-attribute> >> <put-list-attribute name="breadcrumbs" cascade="true" inherit="true"> >> <add-list-attribute> >> <add-attribute expression="${customer.id}"/> >> <add-attribute expression="/customers/${customer.id}/info"/> >> </add-list-attribute> >> <add-list-attribute> >> <add-attribute value="Orders"/> >> <add-attribute >> expression="/customers/${customer.country}/${customer.id}/salesOrders"/> >> </add-list-attribute> >> <add-list-attribute> >> <add-attribute expression="${salesOrder.id}"/> >> <add-attribute >> expression="/customers/${customer.country}/${customer.id}/salesOrders/${salesOrder.id}"/> >> </add-list-attribute> >> </put-list-attribute> >> </definition> >> >> Note here how now my spring controllers need to know nothing about the >> breadcrumbs. In fact the only thing that knows about them is the view and >> the view composition, which I believe is the whole point of a framework like >> tiles, being able to decouple your composition from your controllers, which >> is what I love about tiles. >> >> >> >>> I used the tiles-centric solution back at the time when CSS and DI were >>> barely budding, and their long-term adoption was still questionable, but >>> now I prefer other ways. That being said, I'm totally open to >>> contributions that would be useful to others. >>> >>> >>> >>> >>> Concerning the documentation: I totally agree it needs work, there's a >>> ramp up to learning Tiles 3. Initialization is cumbersome, and as we >>> discussed earlier, the duality between "value" and "expression" is >>> confusing. All of this is documented on the website, but the docs are >>> dry and learning is difficult. Perhaps we could rework the tutorials and >>> update the examples. Another dark area is: how to test? >> >> Would love to help, I've been using tiles for some years and myself only >> stumble onto 3 specific features when I find them, so I don't "know it all", >> but I'd be more than happy to help contribute to docs. >> >>> That being said, my time being limited, I prefer to invest it in >>> simplifying the usage of tiles before documenting the simple solution, >>> as opposed to trying to explain the complex solution in a clear way. >> >> I would tend to agree, and considering it's been that way for a while, maybe >> that's the right approach. Though, how long would the simplified solution >> take to implement? >> >>> So personnally I'm looking at reviewing the docs when tiles can be >>> configured from DI, and run in junit (tiles 3.1, perhaps. My github fork >>> already has the junit part working, and I'm experimenting with DI). >>> >>> Cheers! >>> >>> Nick >>> >>> PS: On 15-07-08 09:21 AM, Brett Ryan wrote: >>>> toString should always be a string representation of a value, not >>> null, alternatives would be "null" or "(null)". >>> >>> +1, definitely >>
