i'm trying build tapestry component called crudentityfield, based on textfield
(core), dialoglink
(tapestry5-jquery) , dialog
(tapestry5-jquery) components, along zone
ajax updates.
my use case quite simple:
crudentityfield render textfield. if know entity id, can enter there directly. if don't know id, can click on
dialoglink
button (select), pops dialog window. dialog lists available entities in table format, , lets filter criteria. once user selects entity, text field automatically refreshed related id (e.g '6'). also, related name/description printed clarity (e.g. '[gipuzkoa]'). snapshots: crudentityfield, pop-up dialog
ideally, logic can encapsulated in single tapestry component. here come issues:
the dialog (
<div t:type="jquery/dialog" t:clientid="dialogidxxx">
, see below) includes search form, , embedded within form (crud form). nested forms not allowed, try un-nest it. however, approach fail, runtime exception when inner form rendering, before have opportunity move it.@afterrender public void afterrender(markupwriter writer) { element body = writer.getdocument().find("html/body"); writer.getdocument().getelementbyid("dialogidxxx").movetobottom(body); }
i tried other approaches, such
@heartbeatdeferred
,rendercommand
, etc. found no way render dialog out of form.
component template:
<t:content> <!-- a) entity field --> <t:zone t:id="entityzone" id="zoneidxxx"> <div class="inputelement"> <t:label for="textfield"/> <input t:id="textfield"/> [<t:body/>] <t:jquery.dialoglink t:dialog="dialogidxxx" class="dialoglink">select</t:jquery.dialoglink> </div> </t:zone> <!-- b) entity dialog --> <div t:type="jquery/dialog" t:clientid="dialogidxxx" params="params" > <table t:id="xa2grid" t:entity="inherit:entity" t:add="actions"> <p:actionscell> <a t:type="eventlink" t:event="select" t:zone="zoneidxxx" t:context="entity.id" href="#">select</a> </p:actionscell> </table> </div> </t:content>
ok, can split component in 2 pieces:
entityfield
(form input field) ,entitydialog
(placed out of form, in page template). not ellegant, though, since approach breaks abstraction.but approach won't work either. zone event triggered
entitydialog
component, , must handled or 1 of containers. zone defined inentityfield
, sibling! (i can paste more code if not clear).
as you've seen, can't render form inside form need delay rendering of dialog until after form has rendered.
so, instead of rendering dialog inside component, use environmental bean. environmental store config dialogs on page
http://tapestry.apache.org/environmental-services.html
include block @ end of every page looks config environment , renders of dialogs. using layout in 1 place.
eg: layout.java
@inject environment environment; @property private dialogconfigs dialogconfigs; @property private dialogconfig dialogconfig; void beforerender() { dialogconfigs = new dialogconfigsimpl(); environment.push(dialogconfigs.class, dialogconfigs); } void afterrender() { environment.pop(dialogconfigs.class); }
layout.tml
<html> <body> <t:body/> <t:loop source="dialogconfigs.values" value="dialogconfig"> <div t:type="jquery/dialog" foo="dialogconfig.foo" bar="dialogconfig.bar"> </t:loop> </body> </html>
crudentityfield.java
@environmental private dialogconfigs dialogconfigs; @parameter private string foo; @parameter private string bar; void beforerender() { dialogconfigs.add(new dialogconfig(foo, bar)); }
Comments
Post a Comment