- I wanted to minimize the amount of Javascript I had to maintain for perform the round-trips
- I wanted to use Struts actions and JSP to render the dynamic content
- My dynamic content contains input elements which must be submittable and maintained across submits
I took a quick look at the prototype.js and decided to use it for performing the asynchronous stuff. It doesn't seem to have much documentation, but browsing the Javascript source helped. I found Using prototype.js v1.3.1
Modifying the main JSP page to dynamically include some content was easy. I had a select list which, when a new value was selected, would asynchronously load some data then present it in a table using displaytags. The values would be editable. Here is what it looked like:
<html:select property="configureApplicationId" styleid="configureApplicationId">
<html:optionscollection property="configureApplicationOptions">
</html:select>
<html:errors property="configureApplicationId">
<div id="configurationSettingsId">
</div>
<script type="text/javascript">
new Form.Element.EventObserver(
'configureApplicationId',
function(element, value) {
new Ajax.Updater(
'configurationSettingsId',
'myAction.do',
{parameters: Form.Element.serialize(element)}
)
}
);
</script>
This sets up an event listener on the change to the configureApplicationId which invokes an asynchronous HTTP post to myAction.do with the parameter configureApplicationId=value. On return, it replaces the content of the configurationSettingsId element with the result of the invocation.
The action is a regular Struts action which populates a form with the given parameter. The action forwards to a plain JSP page which renders the form content. Since the JSP page doesn't contain an <html:form> Struts tag, you have to add the name="formname" attribute to each <html:...> input element as so:
<html:hidden name="configureForm" property="configSettingsSerialized" />
Now when we submit the form after dynamically rendering a portion, the dynamic portion will disappear unless we take steps to re-render it. We could use some more javascript to do another asynchronous round-trip, but that usually has a noticable visual delay. I chose to render the dynamic portion in-line.
To do this we need to make available the same Struts ActionForm that is normally instantiated during the asynchronous round-trip and include the JSP page that is normally forwarded to during the asynchronous round-trip.
To do this, I added a method to the main page form which returned the ActionForm needed for the rendered portion and did a JSP include:
<
<div id="configurationSettingsId">
<c:set scope="request" var="configureForm" value="${mainForm.configureForm}" />
<jsp:include page="/path/to/jsp/myPage.jsp" />
</div>
Of course, for this to work, the main form must be able to populate the sub-form's values such that they can be rendered by the included JSP. That is simply a case of adding the appropriate setters to the main form, or including the same ability to setup the data as the other Action.
No comments:
Post a Comment