Question

A have problem with accessing my custom components (which are used as parts of the form).

Here is the story: I have dynamic form which have few modes of work. Each mode can be selected and loaded into form body with AJAX. It looks like that (template):

<t:form t:id = "form">
    <p class= "calcModeTitle">
        ${message:modeLabel}: <select t:id="modeSelect"
                  t:type="select" 
                  t:model="modesModel" 
                  t:value="selectedMode"  
                  t:blankOption="NEVER" 
                  t:encoder="modeEncoder"
                  t:zone = "modeZone"
        />
    </p>

    <div class="horizontal_tab">
        <t:errors/>
    </div>

    <t:zone t:id="modeZone" id="modeZone" t:update="show">
        <t:if test="showCompany">
            <t:delegate to="block:companyBlock" />
        </t:if>
        <t:if test="showPersonal">
            <t:delegate to="block:personalBlock" />
        </t:if>
        <t:if test="showMulti">
            <t:delegate to="block:multiBlock" />
        </t:if>
    </t:zone>

    <t:block id="companyBlock">
         <t:modes.CompanyMode t:id="company"/>
    </t:block>

    <t:block id="personalBlock">
        <t:modes.PersonalMode t:id="personal" />
    </t:block>

    <t:block id="multiBlock">
        <t:modes.MultiMode t:id="multi" />
    </t:block>

    <div class="horizontal_tab">
        <input type="submit" value="${message:submit_label}" class="submitButton thickBtn"/>
    </div>

</t:form>

AJAX works pretty well and form changes accordingly the "modeSelect" state. But i run into problem when submitting the form. I have in class definition hooks for components placed as:

//----form elements
@Component(id = "form")
private Form form;

@InjectComponent
private CompanyMode company;

@InjectComponent
private PersonalMode personal;

@InjectComponent
private MultiMode multi;

where *Mode classes are my own components, containing form elements and input components. I planned to get access to them during validation, and check values supplied by user with form, but when I am trying to reach anything from them I've got nullPointerException - it seems that component are not initialized in my class definition of form. On the other hand form component is injected properly (I am able to write some error for example). I am a bit lost now. How to properly inject my components to class page containing the form?

Was it helpful?

Solution

Dynamic forms in tapestry are a bit complicated. Tapestry passes a t:formdata request parameter which contains the serialized form entities. This is then used serverside in the POST to re-hydrate initial form state. This must be kept up-to-date with what the client sees.

If you want to add dynamic content to a form via ajax, you will need to use the FormInjector. You might want to take a look at the source code for the AjaxFormLoop to see an example.

If you want to render hidden form fragments and make them visible based on clientside logic, you can use the FormFragment

OTHER TIPS

From tapestry guide:

A block does not normally render; any component or contents you put inside a block will not ordinarily be rendered. However, by injecting the block you have precise control over when and if the content renders.

Try to use here either "t:if" or "t:delegate".

Something like this:

<t:zone t:id="modeZone" id="modeZone" t:update="show">
      <t:delegate to="myBlock" /> 
</t:zone>

<t:block t:id="companyBlock">
     <t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block t:id="personalBlock">
    <t:modes.PersonalMode t:id="personal" />
</t:block>

<t:block t:id="multiBlock">
    <t:modes.MultiMode t:id="multi" />
</t:block>

java:

@Inject
private Block companyBlock, personalBlock, multiBlock;

public Block getMyBlock(){
    if (getShowCompany()) return companyBlock;
    if (getShowPersonal()) return personalBlock;
    return multiBlock;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top