Results 1 to 10 of 10

Thread: Binding selected items (multiple select box)

Hybrid View

  1. #1
    Join Date
    Jul 2005
    Location
    Munich, Germany
    Posts
    153

    Default Binding selected items (multiple select box)

    Hello,

    I'm actually really stuck with binding an n:m object graph to a multiple select box.

    Consider the following domain model (hibernate beans):

    Code:
    public class User
    {
        private Integer id;
        private String username;
        private List<UserRole> userRoles;
    
        // Standard setters and getters
    &#125;
    
    public class Role
    &#123;
        private Integer id;
        private String name;
    
        // Standard setters and getters
    &#125;
    
    public class UserRole
    &#123;
        private User user;
        private Role role;
    
        // Standard setters and getters
    &#125;
    As you see the n:m relation is based on two 1:n relations (User 1:n UserRole n:1 Role).

    In my form I want two multiple select boxes - one box should show all unassigned roles, the other one should show the assigned ones.
    JavaScript buttons should manage the assignment / disassignment (shift entries from the unassigned box to the assigned box, or the other way around).

    My problem is, that I don't really know how to manage this in a professional way. I'd know how to do that manually in onBind(), but I thought it would be more professional to handle that by a custom PropertyEditor. The first thing with a custom PropertyEditor which I don't know is, to which Class I should bind it (List.class, UserRole.class, Role.class). Furthermore I don't know how the html code should look like (the spring related part - spring:bind, spring:transform or whatever).

    I read (and mostly understand) "Spring in Action", "Pro Spring", " Professional Java Development with the Spring Framework", as well es the online documentation and tons of forum topics. Nevertheless I feel totally innocent how this problem could be handled. I found many forum topics about binding multiple select boxes, but I couldn't find one that really helped.


    I'd really much appreciate any help!


    Best

    Oliver

  2. #2

    Default

    I spent a lot of time on the same issue and wasn't able to come up with a satisfactory answer. Here's my best understanding: Spring can only bind form data to complex object relationship through indexed types (List, Map), and the index must be a String. So in your example, you cannot have a List of UserRoles, you would have to have a List of UserRole IDs represented as Strings.

    If you want to do a Map you're really in trouble because, though you can write a custom property editor to convert between a String and an Object, and you can use a Map to index properties with a String index, you can't combine the two, having a Map with a String index that gets converted to an Object type. (I have put in a request for this capability and it's been accepted for version 1.3rc1: http://opensource.atlassian.com/proj...rowse/SPR-1204)

    Editing complex relationships like this by binding your domain object as the command class would then, in my opinion, require too many concessions to my domain model solely to support Spring MVC. As a result I chose to create a transfer object with an interface that mapped well to a form, and then in my controller I manually bind those values to my domain object; this is the same way you would end up doing it in Struts with an ActionForm.

    It might be that I'm missing the boat and there's a way to bind complex domain objects directly to a form without changing the object's interface radically, but I haven't found it yet.

  3. #3
    Join Date
    Jul 2005
    Location
    Munich, Germany
    Posts
    153

    Default

    Thanks a lot for your comment, debradley. I really do much appreciate it!

  4. #4
    Join Date
    Oct 2005
    Location
    Amsterdam
    Posts
    81

    Default Same issue

    I am actually having the same issue and i haven't found an easy answer to my problem yet on this forum. I am willing to use as much as possible my domain model, but it indeed quite hard, as my current nested (Set of Sets...). I am considering writing a command class and to map it manually.
    The CustomCollectionEditor provides almost an answer, but I haven't been able to get to an implementation that works for me... :-(

    Any hints? Thanks!

    Nicolas

  5. #5
    Join Date
    Nov 2004
    Posts
    17

    Default

    Dear all,
    Similar problem...
    Please give us any advice.


    Thanks!
    Last edited by leonchen; Apr 18th, 2006 at 06:19 AM.

  6. #6
    Join Date
    Oct 2004
    Location
    Herndon, VA, US
    Posts
    648

    Default

    Quote Originally Posted by NicolasPeeters
    The CustomCollectionEditor provides almost an answer, but I haven't been able to get to an implementation that works for me... :-(
    Matt Raible wrote an excellent tutorial on how to use CustomCollectionEditor to deal with multiple selections.

    Sometimes if performance is a concern, I tend to take a slightly different approach though - instead of using CustomCollectionEditor.convertElement(), which causes one DAO call per element, I would directly extend PropertyEditorSupport, in which I parse the comma separated strings to ids, and load all the elements in one shot.
    --Jing Xue

  7. #7
    Join Date
    Oct 2005
    Location
    Amsterdam
    Posts
    81

    Default Tricky problem... indeed

    We also extended the CustomCollectionEditor. It basically does the following:
    - retrieve the ID of an object instance
    - transform an instance and return its ID

    On the JSP side, I populate the checkboxes in the case their ID are present in the list of comma-separated values of ID's (or any synthetic key you might want to create) using a "fn:contains" function of JSTL. I realize this last trick might be a discussion point, but it's very concise (and my ID's are always unique), so we went for it...

    Code:
    <c:forEach items="${items}" var="item" varStatus="loopStatus">
    <spring:bind path="project.myItems">
    	<input type="hidden" name="_${status.expression}">
                 <input type="checkbox" name="${status.expression}"
    		value="<c:out value='${item.id}' />"
    	<c:if test="${fn:contains(status.value,item.id)}">checked</c:if> />
    	     		${sl.label} <br />
    </spring:bind>
    </c:forEach>
    Hope it helps!

  8. #8

    Default

    Quote Originally Posted by NicolasPeeters
    using a "fn:contains" function of JSTL. I realize this last trick might be a discussion point...
    Under JSP 2, it's trivial to create an EL function to test for collection containment. I use referenceData to populate the model with all of the choices and a CustomCollectionEditor to bind the multiselect/checkbox group. Then, a simple
    Code:
    ${coll:contains(refItems,curItem)}
    is all it takes to determine if an item should be selected/checked at render time.

    I was surprised at just how easy. Here's the code for the contains function:
    Code:
    public class CollectionUtil {
    
    	public static boolean contains(Collection coll, Object item) {
    		return coll.contains(item);
    	}
    
    	private CollectionUtil() {
    		super();
    	}
    
    }
    And the TLD:
    Code:
    <taglib
    	xmlns="http://java.sun.com/xml/ns/j2ee"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    	version="2.0">
    
    	<description>Java collection support tag library</description>
    
    	<tlib-version>0.1</tlib-version>
    	<short-name>coll</short-name>
    	<uri>http://www.orthogony.com/ns/taglib/collections</uri>
    
    	<function>
    		<description>
    			Check for the existence of an object in a collection.
    		</description>
    		<name>contains</name>
    		<function-class>
    			com.orthogony.web.jsp.taglib.CollectionUtil
    		</function-class>
    		<function-signature>
    			boolean contains(java.util.Collection, java.lang.Object)
    		</function-signature>
    	</function>
    </taglib>
    -dub

  9. #9
    Join Date
    Aug 2004
    Posts
    1,905

    Default

    Hi ojs

    First thing I would suggest is to simplify the problem. Worry about doing a single one-to-many problem, i.e. User and User.getRoles().

    When you select more than one (checkboxes, multi-select etc.) role, your web browser submits a number of String values (role=valueA,role=valueB) which you need to convert into a collection of Roles. So, create a single property editor which converts from that String value into a Role.

    Rather than repeating it all here, read the following and let me know if you have any questions (note it is for checkboxes and arrays, but it should be transferable to multi-select and Sets ) : http://forum.springframework.org/sho...ght=checkboxes

Similar Threads

  1. Replies: 37
    Last Post: Aug 10th, 2009, 03:35 PM
  2. hibernate pagination
    By oliverchua in forum Data
    Replies: 8
    Last Post: Sep 23rd, 2005, 06:06 PM
  3. Replies: 7
    Last Post: Sep 13th, 2005, 01:45 AM
  4. Replies: 0
    Last Post: Jul 1st, 2005, 01:16 AM
  5. Replies: 2
    Last Post: Aug 17th, 2004, 04:16 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •