This blog post concerns the issues I came across attempting to clear two drop downs and a text field in a JSP that itself was a view inside a Spring Webflow (v.2.x).

The layout of the JSP is here: http://gomockingbird.com/mockingbird/index.html?project=559efee20fb22b4a077b4e6652c36f8f54376621

Essentially what my terrible drawing is showing is a list of items and below that list of items three drop downs that when selected, and the save button is clicked, will populate another row in the list. The reason for being inside a Webflow is that this particular problem was part of an enhancement to an existing Webflow.

Initially the flow was very simple. A single view state that had it's save, edit and delete transitions evaluate a single expression and return back to the view. For example a save would bind to the model underneath the drop downs, that model would be added to the list of objects backing the list and coming back to the view one would see the new list with the added item and the drop downs and text field would be blank allowing the user to add another item or continue on into the flow (again please forgiven the primitive mock up, there could be a "next" button in it).

Unfortunately what was happening during the save and edit, but not the remove was the drop downs and text field were maintaining their values upon returning to the view! Upon first glance this didn't make sense. When I looked at the remove transition I noticed I had placed an attribute on the transition as such: 'bind="false"'. That clued me in that something was going on with the binding; that somehow the model I was newing up upon re-entering or entering the view state was not being recognized or not binding or something!

Reviewing the Spring Webflow online documentation I was able to learn more about how the binding actually takes place in Webflow which made sense. The drop down values where bound as whatever path I gave them in the form to the Request and then that Request and it's bound variables was used to populate the model. At this point I think it's a good idea to show you what the form looked like.

form:form id="myForm" modelAttribute="myModel" method="post" action="${save}">
 form:select path="dropBox1"/>
 form:select path="dropBox2"/>
 form:input path="textField"/>
form:form>

So the Request has something like; dropBox1=value, dropBox2=value, textField=value. Then those are bound from the Request to the model as such; myModel.dropBox1 = value, myModel.dropBox2 = value and so on. I know this is a little Web Application 101 for some people so I apologize for that.

It became apparent the values were still in the Request after some Java code processing with the evaluation expression transitions. In fact it appeared, since I was never really leaving the view state that the Request parameters were scoped to the view state perhaps. So a few thoughts entered my mind. If I left the view state, say by calling an action state and then evaluating the java to save/update/delete the object and then came back into the view state that might un-scope those Request parameters and the drop downs and text field would be blank.

Long story short that didn't work. Those Request parameters seemed to be in a much larger scope, obviously if I had switched states in the flow and the values were still in the Request or rather it was still being treated as the same Request it must be flow scoped and the Webflow docs seemed to back this up. A Request per a flow apparently. I was already in a sub-flow so I proceeded to create a sub-sub-flow just for the save action to test it out.

Thwarted again! The drop downs and text field still had their values after going into the sub-sub-flow, and coming back to the sub-flow and into the view. Bear in mind I had tried a number of other things at this point including attempting to new up the model before re-tranisitioning into the flow, newing up the model in the sub-sub-flow, attempting to the model to null before newing it up. But really the model was not the problem! It was getting those darn parameters out of the Request or doing something, anything with them.

Perhaps it was the Ext JS I was using to create the drop downs. As my anger burning towards anything that stood in my way I attempted striping out the ExtJs but to no avail.

I decided upon further research that I could perhaps implement some time of onLoad javascript when loading the form to clear the fields. Adding a attribute to the as such: name="nuke" I would call document.nuke.reset onLoad and pray that worked. It did not.

I decided to add the document.nuke.reset to the $(document).ready(function() {}); That half way worked! It cleared the drop downs but not the text field! Actually it kind of blanked them as my default values when the boxes were empty weren't even showing.

Time to bring out the big guns. I had sub-sub-flows and I had the following TWO JavaScript functions to choose from:

function clear_form() {
 document.nuke.reset();
}
 
function clearForms() {
 var i;
 for (i = 0; (i  document.forms.length); i++) {
 document.forms[i].reset();
 }
}

And I was calling both on document render!

Still only the drop downs were being cleared. At this point I'd like to mention I had tried so many different options that I may have forgotten to mention them. If you ask me if I tried this or that, chances are I may have.

I refocused my attention on the bind attribute, which can only be used in a view state transition. Whatever magic was happening there was allowing the fields to clear. I created an intermediate view simply so I could use the bind attribute. It was a fake view state with a JSP named nuke.jsp that simply transitioned to the real view state but with a bind="false" attribute. Of course you can't just display a view and transition right away so I added in the "document ready" JavaScript the following: Ext.get("nukeForm").dom.submit(); I had created a fake form in my fake view and on load of the view I was going to submit the fake form right away and cause the transition to happen. When this didn't work because calling dom.submit was giving a null error on the dom object I realized this option as the hack it was, slapped myself, and tried on last thing, the last, last thing I could think of.

I decided that I would have to display the list of values and the drop downs separately, to get my two separate view states, in two separate flows. I would have the list on one flow in one view and when clicking save or edit or delete it would transition to a sub-flow with the drop downs in another view state. I didn't really want to spilt the view up because I liked the look and feel but the flow was still fairly natural and it actually worked! The drop downs and the text field cleared and the look and feel was consistant with another part of the flow that was doing the same kind of thing.

It appeared like the Request items were cleared upon entering a new view in a new flow scope, which made sense if any other binding were to happen in that different view, in that different flow scope. I'm hoping in the future the ability to scope the Request to a view may make sense within a single flow.

I welcome your comments!