Title: Problems encapsulating Dialog components in Tapestry 5.3
Tags: java;jquery;tapestry
Question: I'm trying to build a Tapestry component called CrudEntityField, based on ```TextField``` (core), ```DialogLink``` (tapestry5-jquery) and ```Dialog``` (tapestry5-jquery) components, along with ```Zone``` for AJAX updates.

My use case is quite simple:

```
  CrudEntityField will render as a TextField. If you know the entity id,
  you can enter it there directly. If you don't know the id, you can
  click on the ```DialogLink``` button (SELECT), which pops up a Dialog
  window. The Dialog lists all available entities in table format, and
  lets us filter by some criteria. Once the user selects the entity, the
  text field is automatically refreshed with the related id (e.g '6').
  Also, a related name/description is printed for clarity (e.g.
  '[Gipuzkoa]').
  Snapshots: CrudEntityField, Pop-up Dialog
```

Ideally, all this logic can be encapsulated in a single Tapestry component. But here come the issues:


The dialog (```<div t:type="jquery/dialog" t:clientId="dialogIdXXX"&gt;```, see below) includes a search form, and is itself embedded within another form (CRUD form). As nested forms are not allowed, I could try to un-nest it. However, this approach will fail, as I get a runtime exception when the inner form is rendering, before I have the opportunity to 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 as ```@HeartbeatDeferred```, ```RenderCommand```, etc. but I found no way to render the dialog out of the Form.


Component template:

```<t:content&gt;

<!-- A) Entity Field --&gt;
<t:zone t:id="entityZone" id="zoneIdXXX"&gt;           
  <div class="inputElement"&gt;

    <t:label for="textField"/&gt;
    <input t:id="textField"/&gt;           

    [<t:body/&gt;]

    <t:jquery.dialoglink t:dialog="dialogIdXXX" class="dialogLink"&gt;SELECT</t:jquery.dialoglink&gt; 

  </div&gt;
</t:zone&gt;   

<!-- B) Entity Dialog --&gt;
  <div t:type="jquery/dialog" t:clientId="dialogIdXXX" params="params" &gt;            
   <table t:id="xa2grid" t:entity="inherit:entity" t:add="actions"&gt;         

      <p:actionsCell&gt;       
         <a t:type="EventLink" t:event="SELECT" t:zone="zoneIdXXX" t:context="entity.id" href="#"&gt;SELECT</a&gt;                        
      </p:actionsCell&gt;

    </table&gt;                    
  </div&gt;  

</t:content&gt;
```


Ok, so I can split the component in two pieces: ```EntityField``` (form input field) and ```EntityDialog``` (placed out of the Form, in the page template). Not ellegant, though, since this approach breaks the abstraction. 

But this approach won't work either. The zone event is now triggered by the ```EntityDialog``` component, and must be handled by itself or one of its containers. But the zone is defined in ```EntityField```, which is now a sibling! (I can paste more code if not clear).



Here is the accepted answer: As you've seen, you can't render a form inside a form so you will need to delay the rendering of the dialog until after the form has rendered.

So, instead of rendering the dialog inside your component, use an environmental bean. The environmental will store the config for all dialogs on the page

http://tapestry.apache.org/environmental-services.html

Include a block at the end of every page which looks up the config from the environment and renders all of the Dialogs. Hopefully you are using a layout so this will be in one 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&gt;
    <body&gt;
        <t:body/&gt;
        <t:loop source="dialogConfigs.values" value="dialogConfig"&gt;
            <div t:type="jquery/dialog" foo="dialogConfig.foo" bar="dialogConfig.bar"&gt;  
        </t:loop&gt;
    </body&gt;
</html&gt;
```

CrudEntityField.java

```@Environmental
private DialogConfigs dialogConfigs;

@Parameter
private String foo;

@Parameter
private String bar;

void beforeRender() {
    dialogConfigs.add(new DialogConfig(foo, bar));
}
```



{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2013:00:06/14/13', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<java><jquery><tapestry>', 'Title': 'Problems encapsulating Dialog components in Tapestry 5.3', 'ViewCount': 485, 'id': 17104810, 'user_AboutMe': '<p>Software Architect</p>\n', 'user_AccountId': 2403221.0, 'user_DisplayName': 'aritzbastida', 'user_Reputation': 43.0, 'user_Views': 7.0, 'user_id': 2100419.0}}