PDA

View Full Version : FAQ: howto display checkboxes/multiselect


Colin Yates
Aug 26th, 2005, 07:44 AM
The question of how to support checkboxes keeps appearing over and over again. This is how I deal with it:

Assume:


class MyClass {
private String id;
private String name;
// accessors
}

class MyBackingObject {
private MyClass[] myClasses;
// accessors
}


In my simpleFormController I register a MyClassPropertyEditor in initBinder:

public initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
binder.registerCustomEditor(MyClass.class, new MyClassPropertyEditor());
}


then in reference data I construct a map of *all* possible instances of MyClass:


public Map referenceData(HttpServletRequest request, Object command, Errors errors) throws Exception {
MyBackingObject form = (MyBackingObject) command;
Set selectedMyClasses = new HashSet().addAll(Arrays.asList(form.getMyClasses() ));

Map allMyClasses = new HashMap();
for (Iterator i = myDAO.getAllMyClasses(); i.hasNext(); ) {
MyClass myClass = (MyClass) i.next();
allMyClasses.put(myClass, new Boolean(selectedMyClasses.contains(myClass));
}

Map model = new HashMap();
model.put("allMyClasses", allMyClasses);
return model;
}


then in my jsp:


<c:forEach items="${allMyClasses}" var="allMyClassesEntry">
<input type="checkbox" name="command.myClasses" value="${allMyClassesEntry.key.name}" <c:if test="${allMyClassesEntry.value}">selected</c:if>></input>
</c:forEach>


I typed this in, so it probably doesn't compile, but you get the idea ;)

HTH.

martinl
Aug 27th, 2005, 02:53 PM
You forgot to show the code of MyClassPropertyEditor. ;)

ypj
Sep 3rd, 2005, 03:10 AM
Then how to bind the items?

ypj
Sep 3rd, 2005, 04:03 AM
And another questioin: Dose c:forEach support Map? Can a Map be iteratored by the froEach tag?

Cowboy Bob
Sep 3rd, 2005, 05:37 AM
And another questioin: Dose c:forEach support Map? Can a Map be iteratored by the froEach tag?

Yes, you get an Entry object in your var with "key" and "value" values.

<spring:bind path="searchCommand.areaCode">
<select name="areaCode">
<option value="">--</option>
<c:forEach var="county" items="${countyMap}">
<option value='<c:out value="${county.key}"/>' <c:if test="${status.value == county.key}">selected</c:if>><c:out value="${county.value}"/></option>
</c:forEach>
</select>
</spring:bind>

Bob

ypj
Sep 3rd, 2005, 10:42 AM
:) Thanks Bob.

kermie5000
Sep 21st, 2005, 06:24 PM
also would like to see myclasspropertyeditor...

Colin Yates
Sep 22nd, 2005, 05:55 AM
The source code for myClassPropertyEditor is absolutely pointless ;) It entirely depends on what the class is an how to retrieve it.

For example, if I myClass was a persisted class, i.e. a User and I was entering the user name, then my propertyEditor might look like:


public final UserPropertyEditor extends PropertyEditorSupport {
private final UserDAO dao;

public UserPropertyEditor (final UserDAO theDAO) {
this.dao = theDAO;
}

public String getAsText() {
User user = (User) getValue();
return user.getUserName();
}

public void setAsText(final String value) {
try {
User user = dao.findUser(value);
super.setValue(user);
} catch (final ObjectRetrievalFailureException e) {
LOGGER.debug("Cannot find user with username: " + value);
super.setValue(null);
}
}
}


HTH.

Trickle
Oct 6th, 2005, 11:14 AM
Ytesco, I have tried what you have said above and I still can not get my valuies to bind. I have a class that only contains a list, and that list gets populated with my value class that holds all the data. Everything works fine except that the variables on my value class are not getting set with the values from the page when I submit. I have a feeling that it has something to do with the Propert Editor, but I can not figure out how to set that up.

Do you have any ideas or need more information?

Colin Yates
Dec 11th, 2005, 06:27 AM
Can you post your code please.

paulr
Aug 31st, 2006, 10:29 AM
The question of how to support checkboxes keeps appearing over and over again. This is how I deal with it:

Assume:


class MyClass {
private String id;
private String name;
// accessors
}

class MyBackingObject {
private MyClass[] myClasses;
// accessors
}


In my simpleFormController I register a MyClassPropertyEditor in initBinder:

public initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
binder.registerCustomEditor(MyClass.class, new MyClassPropertyEditor());
}


then in reference data I construct a map of *all* possible instances of MyClass:


public Map referenceData(HttpServletRequest request, Object command, Errors errors) throws Exception {
MyBackingObject form = (MyBackingObject) command;
Set selectedMyClasses = new HashSet().addAll(Arrays.asList(form.getMyClasses() ));

Map allMyClasses = new HashMap();
for (Iterator i = myDAO.getAllMyClasses(); i.hasNext(); ) {
MyClass myClass = (MyClass) i.next();
allMyClasses.put(myClass, new Boolean(selectedMyClasses.contains(myClass));
}

Map model = new HashMap();
model.put("allMyClasses", allMyClasses);
return model;
}


then in my jsp:


<c:forEach items="${allMyClasses}" var="allMyClassesEntry">
<input type="checkbox" name="command.myClasses" value="${allMyClassesEntry.key.name}" <c:if test="${allMyClassesEntry.value}">selected</c:if>></input>
</c:forEach>


I typed this in, so it probably doesn't compile, but you get the idea ;)

HTH.

Has anyone succesfully got this type of example working using the <form:checkbox> tag from spring 2.0?

...i can't seem to get checkboxes checked when editing an object. All the docs/examples i've seen so far use 'simple' objects for reference data when populating the checkbox -Strings,Integers etc, while i want to use a 'domain' object.

Rgds
Paul

ritikavk001
Jul 27th, 2007, 08:22 PM
Hi, I am a newbie to Spring and I am having trouble binding a list of objects.

Here is my code:
public class ECNFeeSchedFormModel {
private ECNFeeSched[] ECNFeeScheds;

//getters and setters
}

public class ECNFeeSched {
private String client_id;
//getters and setters
}

The controller is bound to the ECNFeeSchedFormModel

public class ECNFeeSchedFormController extends SimpleFormController {
public ECNFeeSchedFormController(){
setCommandName("eCNFeeSchedFormModel");
setCommandClass(ECNFeeSchedFormModel.class);
setFormView("eCNFeeSchedForm");
setSuccessView("eCNFeeSchedFormDone");
}

protected Map referenceData(HttpServletRequest request) throws Exception {
Map reference = new HashMap();

// Put a list of ECNFeeScheds in the requestScope
List eCNFeeScheds = new ArrayList();
eCNFeeScheds.add(new ECNFeeSched("xyz0"));
eCNFeeScheds.add(new ECNFeeSched("xyz1"));
reference.put("ECNFeeScheds", eCNFeeScheds);
return reference;
}


}

In my JSP i have

<form:form commandName="eCNFeeSchedFormModel" name="ECNFeeSchedForm"> <spring:bind path="eCNFeeSchedFormModel.ECNFeeScheds">
<c:forEach items="${requestScope.ECNFeeScheds}" varStatus="varStatus" var="var">
<spring:bind path="eCNFeeSchedFormModel.ECNFeeScheds[${varStatus.index}].client_id">
<input type="text" name="ECNFeeScheds" value="<spring:message text='${var.client_id}'/>" ></input>
</spring:bind>
</c:forEach>
</spring:bind>
<td><input type="submit" name="Submit" value="Submit" /></td>

</form:form>


Also here is how my bean is setup:
<bean name="/eCNFeeSched.htm" class="com.bofa.gcib.gfx.fxpbAdmin.spring.ECNFeeSchedForm Controller">

</bean>



Now when I run the app, I get the following exception:
org.springframework.beans.NullValueInNestedPathExc eption: Invalid property 'ECNFeeScheds[0]' of bean class [com.bofa.gcib.gfx.fxpbAdmin.formModel.ECNFeeSchedF ormModel]: Cannot access indexed value of property referenced in indexed property path 'ECNFeeScheds[0]': returned null


I know that LoopTagStatus resolves the index. But I am using JSTL 1.0 and not 1.1. So is this why the its not able to resolve the index?

Without the spring:bind tags.. the values "xyz0" and "xyz1" are displayed in text boxes... but that is no use without the binding

Can anyone please help?

only2san
Jul 30th, 2007, 06:34 PM
Hi
I'm also facing the same issue. Did you happen to find a solution. Please let me know if you have one/.