Hello, I have 3 nested object. A survey, a section and a question. A survey will contain sections and a section will contain questions. I want to create a single page editor for this nested object using ajax.
In add survey page i have created two zone, survey zone and sectionListZone. The survey zone content will depend on a flag. It can show an input form for the survey or a view of the survey data. The sectionListZone content is a SectionHolder component (custom component for handling the section). The SectionHolder component also contains two zone, sZone and qZone. The sZone content also depend on a flag, to show an input form for the section or to view the section data. The qZone content is a QuestionHolder component (custom component for handling the questions). I've managed to create the add survey page to add & view the survey data. I also manage to create the section holder component by using the same pattern as the add survey page (using ajax response renderer to render both zone when the form is submitted). The problem is in the SectionHolder component i can't render multiple zone using ajax renderer. Returning a block from onSuccess will work. But using ajax renderer to render the zone will result this error : Element 'sZone' does not have an associated Tapestry.ZoneManager object. Communication with the server failed: TypeError: Cannot call method 'getStorage' of null Here's my code for the Add Survey page & the Section Holder. Thanks === Add Survey TML === <t:zone t:id="surveyZone" id="surveyZone"> <form t:type="form" t:id="frmCreateSurvey" t:zone="^"> <div> <t:delegate to="surveyBlock"/> </div> <div> <t:errors/> </div> </form> <hr/> </t:zone> <div> <t:zone t:id="sectionListZone" id="sectionListZone"> <t:delegate to="sectionListBlock"/> </t:zone> </div> <t:block id="addSurveyBlock"> <t:label for="title"/> <t:textfield t:id="title" value="survey?.title" t:validate="required, maxlength=35" size="35"/> <input type="submit" value="Save" class="btn btn-sm btn-primary"/> </t:block> <t:block id="viewSurveyBlock"> SURVEY BLOCK <br/> Title : ${survey?.title} <a t:type="actionlink" t:id="editSurvey" t:zone="surveyZone" href="#" class="btn btn-sm btn-primary">Edit</a> </t:block> <t:block id="viewSectionListBlock"> <t:section.SectionHolder t:id="sectionHolder"/> </t:block> <t:block t:id="emptyBlock"/> ====== Add Survey.Java ========= @Inject private AjaxResponseRenderer ajaxRenderer; @Inject private Block addSurveyBlock, viewSurveyBlock, viewSectionListBlock, emptyBlock; @Inject private Request request; @InjectComponent private Zone surveyZone, sectionListZone; @Property @Persist // TODO erase this when we use database private Survey survey; @Persist private boolean isReadyToPublish; @Persist private boolean isEditSurvey; @Persist private boolean isSectionShown; void onSuccess() { isEditSurvey = false; isSectionShown = true; if(request.isXHR()) { ajaxRenderer.addRender(surveyZone).addRender(sectionListZone); } } public Object getSurveyBlock() { return isEditSurvey ? addSurveyBlock : viewSurveyBlock; } public Object getSectionListBlock() { return isSectionShown? viewSectionListBlock : emptyBlock; } void onActionFromEditSurvey() { isEditSurvey = true; if(request.isXHR()) { ajaxRenderer.addRender(surveyZone); } } === SectionHolder Component tml === <t:content> <h4>Section</h4> <t:zone t:id="sZone" id="sZone"> <form t:type="form" t:id="frmCreateSection" t:zone="^"> Section 1 <div id="sectionDiv"> <t:label for="name"/> <t:textfield t:id="name" value="name" /> <input class="btn btn-sm btn-primary" type="submit" value="Save"/> </div> <div> <t:errors/> </div> </form> </t:zone> <div> <t:zone t:id="qZone" id="qZone"> Question Block </t:zone> </div> </t:content> === Section Holder.java === @Inject private Request request; @Inject private AjaxResponseRenderer ajaxRenderer; @InjectComponent private Zone sZone, qZone; @Property private String name; void onSuccess() { System.out.println("Success!"); if(request.isXHR()) { ajaxRenderer.addRender(sZone).addRender(qZone); } } -- http://www.mreunionlabs.net/ <http://www.mreunion-labs.net/> twitter : @mreunionlabs page : https://plus.google.com/104168782385184990771