Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Table of Contents
maxLevel2

 

 


...


In Adding an Input Field to a Component, it is explained how to add simple input fields to the several component types that XperienCentral supports. This topic explains how to add complex fields to a component.

...

The first step is to define the property in the form backing object:

 


Code Block
themeEclipse
private String[] myHobbies = null;

public String[] getHobbies() {
return myHobbies;
}
   
public void setHobbies(String[] hobbies) {
	myHobbies = hobbies;
}

 


We need to define what hobbies are available to select from. We define these statically also in the Form backing object class:

 


Code Block
themeEclipse
public static String[] HOBBIES = new String[] {"Candlemaking", "Games", "Gardening", "Collecting", "Juggling", "Photography", "Pottery", "Scrapbooking", "Writing"};

 


The next step is to modify the JSP in order to display the checkboxes. Since the hobbies contained by the form backing object will not be accessible from the JSP and we did not define a getter for it, we add this to the reference data in the panel controller.

 


Code Block
themeEclipse
public Map<String, Object> referenceData(HttpServletRequest request, Object command, Errors errors) throws Exception {
	Map<String, Object> data = super.referenceData(request, command, errors);
	data.put("allhobbies", CustomTabFBO.HOBBIES);
	return data;
}

...


The only thing left to do is to add the multiple selection fields in the edit JSP and bind them onto the "hobbies" property. Since there is no standard JSP tag for doing this, we bind the value from the selection field manually onto this property as follows:

 


Code Block
themeEclipse
<spring:bind path="command.hobbies">
	<select name="${status.expression}" multiple>
		<c:forEach var="hobby" items="${allhobbies}">
			<option value="${hobby}" <c:if test="${wmfn:contains(hobby, command.hobbies)}"> selected</c:if>> ${hobby}</option>
		</c:forEach>
	</select>
</spring:bind>

...


Because we use the wmfn tag library, we must explicitly import that library in the JSP: 


Code Block
themeEclipse
<%@taglib uri="http://www.gx.nl/taglib/functions" prefix="wmfn" %>

...


Back to Top

 


...

Editing Multi-value Property with Multiple Checkboxes

...

Earlier in this topic we added the "hobbies" property to the form backing object and wrote all hobbies to the allhobbies attribute in the reference data. The only difference is that we now want the "hobbies" property to use multiple checkboxes instead of one multiple selection field. Again, there is no standard JSP tag for doing this, so we bind the value from the checkboxes manually onto this property as follows:

 


Code Block
themeEclipse
<spring:bind path="command.hobbies">
	<c:forEach var="hobby" items="${allhobbies}">
		<input type="hidden" name="_${status.expression}" value="visible" />
		<input type="checkbox" name="${status.expression}" value="${hobby}"
			<c:if test="${wmfn:contains(hobby, command.hobbies)}"> checked="checked"
			</c:if> 
		/>
 		${hobby}<br/>
	</c:forEach>
</spring:bind>

 


As a result on each submit setHobbies will be invoked with only those hobbies that were selected.

 


Back to Top

 


...

Editing Multi-value Property with Multi-selection Field and Multiple Checkboxes

...

The values of the option fields in the selection field can simply be bound onto the "hobbies" property directly. We must take care to filter out the values that have already been assigned. The code snippet below shows how to bind the values from the multiple selection field onto the "hobbies" property. 


Code Block
themeEclipse
<spring:bind path="command.hobbies">
	<select name="${status.expression}" multiple>
		<c:forEach var="hobby" items="${allhobbies}">
			<c:if test="${!wmfn:contains(hobby, command.hobbies)}"> 
				<option value="${hobby}"> ${hobby}</option>
 			</c:if>
 		</c:forEach>
	</select>
	<wmedit:button type="submit" key="add"/>
</spring:bind>

...

 



Note

The HTML is stripped from this code snippet since it is not the intention of this topic to discuss how to properly render the "selection" field and corresponding "Submit" button.

 


The next step is to display the current values of the property and add the Delete checkboxes to delete those values. This is a slightly more complicated process. The Spring binding mechanism binds values posted from checkboxes only if they are enabled. This works fine if we want to use the checkbox to assign values, but it is less suitable for this case because we want the value to be removed if the checkbox is enabled. The way Spring binding deals with checkboxes must be inverted, that is, values should only be bound onto the "hobbies" property if the checkbox is not checked.

In order to do so, an additional hidden input field has to be added that contains the value to be set on the "hobbies" property if the delete checkbox is not selected: 


Code Block
themeEclipse
<input type="hidden" name="${status.expression}" value="${hobby}"/>

...


Subsequently, the onchange method of the checkbox must be overridden in order to disable this hidden input field when the checkbox is selected. This prevents the field from being posted and thus bound to the "hobbies" property by Spring. The following JavaScript function is added to support this conditional disabling of the hidden input field:

 


Code Block
themeEclipse
<script type="text/javascript" language="javascript">
	function disableCheckbox(id) {
		var checkbox = document.getElementById(id);
			if (checkbox.checked) {
				checkbox.disabled=false;
			}
			else {
				checkbox.disabled=true;
			}
		}
</script>

 


Finally, the code snippet below creates the hidden input fields for the current values of the "hobbies" property and disables each of these values when the corresponding delete checkboxes are selected.

 


Code Block
themeEclipse
<spring:bind path="command.hobbies">
	<c:forEach var="hobby" items="${command.hobbies}" varStatus="loop">
		<input type="hidden" id="${status.expression}_${loop.index}" name="${status.expression}" value="${hobby}"/> 
		${hobby} 
		<input type="checkbox" 
			onchange="disableCheckbox('${status.expression}_${loop.index}');"/>
		<fmt:message key="delete " /><br/>
	</c:forEach>
</spring:bind>

 


As a result, only those values are bound by Spring onto the "hobbies" property which are either added by the multiple selection field or were already assigned and the corresponding delete checkbox was not checked.

 


Note

This approach does not require any specific implementation of the controller or form backing object.

...


Back to Top

 


...

Editing Multi-value Property with Single Selection Field and Multiple Checkboxes

...

To provide a workaround for this, a function must be defined that is invoked just before submitting the form. This function must check whether the value of this selection field is empty and, if so, disable it so that the field value is not posted. In case of a panel, the JavaScript function would look like this:

 


Code Block
themeEclipse
<script type="text/javascript" language="javascript">
	function saveForm() {
		var select = document.getElementById('empty_select');
		if (select.value == '') {
			select.disabled=true;
		}
		else {
			select.disabled=false;
		}
		formobj = document.getElementById("saveform");
		formobj.submit();
	} 

 


The code snippet above assumes the empty dummy field of our selection field has the ID empty_select. The code snippet below shows how to render the single selection field:

 


Code Block
themeEclipse
<select name="${status.expression}">
	<option id="empty_select" value="">&gt; Select a hobby</option>
		<c:forEach var="hobby" items="${allhobbies}">
			<c:if test="${!wmfn:contains(hobby, command.hobbies)}">
				<option value="${hobby}"> ${hobby}</option>
			</c:if>
		</c:forEach>
</select>

...


Back to Top