I have spent way too much time on this stupid problem today.
So I just want to have two SelectManyListBoxes, an add button, and a remove button. You select things in the left listbox and press add to put them in the right listbox. You select things in the right listbox and click remove to remove them from the right listbox. Sounds easy enough...
Here is my code right now (simplified). Yes I realize this code doesn't do what I said I wanted it to do but this is what it has become after I have removed more and more of it just to get something to work.
public String addUsersToSEMessage()
seMessage.getSelectRecipients().add(new SelectItem("test", "test"));
public String removeUsersFromSEMessage()
users.getSelectItems().add(new SelectItem("test", "test"));
So, I would expect that when one clicks the add button (which is connected to the add method) that an item called "test" will be added to the right listbox. This is indeed what happens... UNLESS anything is selected in the left listbox. As long as nothing is selected in the left listbox, there is an item called test added to the right listbox. If there is anything selected in the left listbox, then clicking the button simply clears all selections from the left listbox and does nothing else. This is a problem since the only time it would make sense to click the add button is when at least one thing is selected!
Also, I would expect that when one clicks on the remove button, an item called "test" will be added to the left listbox. This couldn't be more wrong. Actually nothing happens whatsoever when I press the button if nothing is selected in the right listbox. If something is selected, then everything in the right listbox become selected. This may simply be because everything in the right listbox is identical ("test") but in any case, nothing is ever added to the left listbox. Not that I ever want anything added to the left listbox, I'm just trying to get some verification that my code is being run by doing something that I know works because it works with the other button right next to it!
First of all, you should know that a "shuttle control", as they are known, is already available pre-coded, pre-debugged in some of the third-party extension tagsets such as RichFaces.
But, if that's not an option, there are several things to consider.
The first thing is to bear in mind that HTTP is not an interactive client/server protocol. It's batch-oriented request/response, where nothing happens until you submit a form (via commandButton or commandLink). And when you do, the entire form gets submitted, not just parts of it. And in the reponse, the entire page will be redrawn, which can be annoying.
The second thing is like unto the first. If any control on the form contains invalid data, whether it is related to the item you're interested or not, the entire process is defeated. The backing bean's properties will not updated and the action method will not be invoked.
The final result is that something like your simplified code would not work very well, either functionally or visually. So it's better to use AJAX to allow the various components of your composite control to act as a unit (or, better yet, go find one of the composite controls that already work!). If you use AJAX, you can pare down the submitted values to only the elements of your composite control and you can make the response do a partial page update (only the control and related items) instead of re-drawing the entire web page.
One other thing. A true shuttle control would employ the same action to remove item(s) from one selection list and add it to the other. I don't do much work with selectManyListbox, however, so I cannot supply sample code.
An IDE is no substitute for an Intelligent Developer.
Well, I've spent all day now trying to install RichFaces to no avail. Following their instructions doesn't do anything but break the application such that it can't find any of the pages anymore... and it still doesn't understand the tag lib declarations I put at the top of the pages to use Richfaces. This one little stupid page is getting really frustrating.
You also need to configure the RichFaces filter in WEB-INF/web.xml
You can probably safely omit the context-params, but the filter and its associated filter-mapping are essential. If I'm not mistaken, RichFaces v3 also has issues with the built-in Facelets for JSF2 and requires the inclusion and configuration of a local Facelets JAR. I'm using jsf-facelets-1.1.14.jar.
Finally, you might need to add this:
disclaimer: This configuration applies to the Tomcat6 appserver. Some changes may be required when other servers (especially full-stack J2EE servers) are used.