-
1. Re: Implementing a multi-select table
texan Aug 15, 2006 7:24 PM (in response to zzzz8)I think that one way is to map your checkbox to an attribute on the entity. In your listener method, you iterate through the data model list and call something like "getSelected()" or whatever the boolean attribute is named.
I'd would like to know if there is a way in Seam to use the @DataModelSelection annotation on a collection instance variable instead of a single bean, but I'm not far enough along in my project to need that (so I haven't tried it). -
2. Re: Implementing a multi-select table
zzzz8 Aug 15, 2006 7:31 PM (in response to zzzz8)Hi texan,
That's one way of doing it, but I don't want to modify the entity (or class) to add a "selected" attribute in the entity. Moreover, there are cases when one cannot (easily) do this - e.g. the class has been created by JAX-RPC, etc. It would be cleaner if one did not have to pollute the entity with an extra attribute. -
3. Re: Implementing a multi-select table
texan Oct 19, 2006 7:02 PM (in response to zzzz8)Did you find a workable solution to this?
-
4. Re: Implementing a multi-select table
jazir1979 Oct 19, 2006 7:14 PM (in response to zzzz8)
You may find this to be overkill, but rather than modifying your entity I suppose you could wrap it in a value object that contains the selected attribute."zzzz8" wrote:
Hi texan,
That's one way of doing it, but I don't want to modify the entity (or class) to add a "selected" attribute in the entity. Moreover, there are cases when one cannot (easily) do this - e.g. the class has been created by JAX-RPC, etc. It would be cleaner if one did not have to pollute the entity with an extra attribute. -
5. Re: Implementing a multi-select table
zzzz8 Oct 20, 2006 2:16 AM (in response to zzzz8)What I did is basically added some code in the getters and setters methods that are bound to the boolean checkbox. I'm pretty sure there's a better way of doing this, and if anyone knows, please tell me. But I believe this is probably what jazir had in mind and here's what I implemented a while back:
@Name("testJobList") @Stateful public class TestBean implements TestLocal { @DataModel("JobList") private List<JobStatus> statusList = null; @DataModelSelection("JobList") private JobStatus jobSelected; private Map<String, Boolean> selectedMap = null; private boolean selected; @Factory("JobList") public final void retrieveJobs() { selectedMap = new HashMap<String, Boolean>(); List<JobStatus> jobStatus = ... ; // get jobStatus object } public final String performAction() { for (JobStatus tempJob : statusList) { // Assuming a JobStatus job has fields (with getters) attr1 String attr1 = tempJob.getAttr1(); if (selectedMap.get(attr1)) { // perform action code here... } } return "goToPage"; } public final boolean isSelected() { if (jobSelected != null && selectedMap != null) { String key = jobSelected.getAttr1(); Boolean value = selectedMap.get(key); if (value == null) { return false; } else { return value; } } else { return false; } } public final void setSelected(final boolean inputSelected) { if (selectedMap != null && jobSelected != null) { String key = jobSelected.getAttr1(); selectedMap.put(key, inputSelected); } } @Remove @Destroy public void destroy() { } }
Here's the JSP markup:<h:form> <h:dataTable value="#{JobList}" var="selectJob"> <h:column> <h:selectBooleanCheckbox value="#{testJobList.selected}" /> </h:column> <h:column> <f:facet name="header"> <h:outputText value="attr1" /> </f:facet> <h:outputText escape="true" value="#{selectJob.attr1}" /> </h:column> <h:column> <f:facet name="header"> <h:outputText value="attr2" /> </f:facet> <h:outputText value="#{selectJob.attr2}" /> </h:column> <h:commandButton value="performAction" action="#{testJobList.performAction}" type="submit" /> </h:form>
This code for the getters and setters is probably a little muddled because I'm using the Tomahawk extended datatable to sort things (I took out the Tomahawk extended datatable JSF markup from the JSP). In this case, my unique identifier for the object would be attr1. I believe the setters and getters could probably be simpler (and one should probably use a List instead of a Map), something like this:List selectedList; public final boolean isSelected() { return selectedList.contains(jobSelected); // or return selectedList.contains(jobSelected.getAttr1()); } public final void setSelected(final boolean inputSelected) { if (inputSelected) { selectedList.add(jobSelected); // or selectedList.add(jobSelected.getAttr1()); } }
But the whole point here is that one needs to add some more code (more than the usual stuff) in the getters/setters in the value binding for the boolean checkbox - and make a note that JSF iterates through all the rows of the datatable - and that one can use this to your advantage in the getters/setters. This works for me and I didn't have to modify the entity... I was probably not clear in my explanation (I gotta go to sleep :) ), but I hope this helps. -
6. Re: Implementing a multi-select table
texan Oct 20, 2006 10:11 AM (in response to zzzz8)That's a novel approach that I wouldn't have thought of.
I also think that it wouldn't be too bad to wrap the bean in a decorator class, as Jazir suggested, except for the small overhead of creating a wrapper for each instance in your collection.
For myself, I went low-budget and just added a "selected" attribute to the domain object. While this in an old anti-pattern (failing to decouple your business logic from your UI logic), I've begun to have more tolerance for that in recent years, probably due to the easy refactoring capabilities of Eclipse. That is, most patterns like that exist for a couple of reasons: (1) avoid having to change too much code when the UI changes, and (2) allowing you to reuse your business objects in multiple UI implementations. We all got excited at the prospect of #2 several years ago, but after about 10 years of Java development, I have actually never had more than one UI for an application. I guess I've led a sheltered life.
Anyway, now I don't worry too much about that sort of thing, and Seam certainly makes it easy to violate a few (hopefully outdated) patterns like this.