0

Suppose I have to render multiple checkboxes inside a data table as shown below:

    <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"   
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jstl/core"
      >
    <h:head>
        <!-- <h:outputStylesheet library="css" name="table-style.css"  /> -->
    </h:head>

    <h:body>

        <h1 align="center">Generate Exam</h1>
        <hr/>
        <h:form id="form">
            <h:panelGrid columns="2" width="100%">
                <h:panelGroup layout="block" style="text-align:center">
                    <h3>Level</h3>
                    <h:selectOneMenu value="#{examBean.candidateLevel}">
                        <f:selectItem itemValue="SR" itemLabel="Senior Level" />
                        <f:selectItem itemValue="MD" itemLabel="Mid Level" />
                        <f:selectItem itemValue="JR" itemLabel="Junior Level" />
                    </h:selectOneMenu>
                </h:panelGroup>
                <h:panelGroup layout="block" style="text-align:center">
                    <h3>Candidate</h3>
                    <h:selectOneMenu value="#{examBean.selectedCandidateId}">
                        <f:selectItems value="#{examBean.candidateList}" var="candidate" itemLabel="#{candidate.name}" itemValue="#{candidate.id}"/>
                    </h:selectOneMenu>
                </h:panelGroup>
            </h:panelGrid>
            <hr/>
            <h:dataTable value="#{examBean.parentCategoryList}" var="cat" binding="#{table}">
                <h:column>
                    <h:outputText value="#{cat.name}"/>
                    <h:commandButton id="button" type="button" value="+" onclick="expand('#{table.rowIndex}');"/>
                    <br/>
                    <h:selectManyCheckbox id="checkbox" value="#{examBean.selectedCategoryList}" style="display:none">
                        <f:selectItems value="#{cat.subCategoryList}" var="sub" itemLabel="#{sub.name}" itemValue="#{sub.id}"/>
                    </h:selectManyCheckbox>
                </h:column>
            </h:dataTable>
            <hr/>
            <h:panelGrid columns="1" width="100%" layout="block" style="text-align:center">
                <h:panelGroup style="text-align:center">
                    <h:commandButton value="Generate Exam" action="#{examBean.generateExam()}" />
                    <h:commandButton value="Reset" type="reset" />
                </h:panelGroup>
            </h:panelGrid>
        </h:form>

        <script type="text/javascript">
            function expand(val) {
                var button = "form:j_idt18:" + val + ":button";
                var checkbox = "form:j_idt18:" + val + ":checkbox";
                var buttonElement = document.getElementById(button);
                var checkboxElement = document.getElementById(checkbox);
                if(checkboxElement.style.display == 'none') {
                    checkboxElement.style.display = 'block';
                    buttonElement.value = '-';
                } else {
                    checkboxElement.style.display = 'none';
                    buttonElement.value = '+';
                }
            }
        </script>   
    </h:body>
</html>

The value attribute in all the checkboxes are the same - #{examBean.selectedCategoryList}. selectedCategoryList is declared as a List<String>property in my bean as shown below:

package com.gtp.iqp.presentation.managedBeans;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gtp.iqp.business.bo.Candidate;
import com.gtp.iqp.business.bo.Category;
import com.gtp.iqp.business.delegate.CandidateDelegate;
import com.gtp.iqp.business.delegate.CategoryDelegate;
import com.gtp.iqp.business.delegate.ExamDelegate;
import com.gtp.iqp.presentation.dto.CandidateSubCategoryList;

@SuppressWarnings("serial")
@Component
public class ExamBean extends BaseManagedBean {

    @Autowired
    private CategoryDelegate               categoryDelegate;
    @Autowired
    private CandidateDelegate              candidateDelegate;
    @Autowired
    private ExamDelegate                   examDelegate;
    private List<Category>                 parentCategoryList;
    private List<String>                   selectedCategoryList;
    private List<Candidate>                candidateList;
    private String                         selectedCandidateId;
    private String                         candidateLevel;

    public ExamDelegate getExamDelegate() {
        return examDelegate;
    }
    public void setExamDelegate(ExamDelegate examDelegate) {
        this.examDelegate = examDelegate;
    }
    public String getSelectedCandidateId() {
        return selectedCandidateId;
    }
    public void setSelectedCandidateId(String selectedCandidateId) {
        this.selectedCandidateId = selectedCandidateId;
    }
    public List<Candidate> getCandidateList() {
        this.candidateList = candidateDelegate.getAllCandidates();
        System.out.println("Cands: " + candidateList.size());
        return candidateList;
    }
    public void setCandidateList(List<Candidate> candidateList) {
        this.candidateList = candidateList;
    }
    public CandidateDelegate getCandidateDelegate() {
        return candidateDelegate;
    }
    public void setCandidateDelegate(CandidateDelegate candidateDelegate) {
        this.candidateDelegate = candidateDelegate;
    }
    public String getCandidateLevel() {
        return candidateLevel;
    }
    public void setCandidateLevel(String candidateLevel) {
        this.candidateLevel = candidateLevel;
    }
    public CategoryDelegate getCategoryDelegate() {
        return categoryDelegate;
    }
    public void setCategoryDelegate(CategoryDelegate categoryDelegate) {
        this.categoryDelegate = categoryDelegate;
    }
    public List<Category> getParentCategoryList() {
        selectedCategoryList = new ArrayList<String>();
        parentCategoryList = categoryDelegate.getParentCategories();
        return parentCategoryList;
    }
    public void setParentCategoryList(List<Category> parentCategoryList) {
        this.parentCategoryList = parentCategoryList;
    }
    public List<String> getSelectedCategoryList() {
        return selectedCategoryList;
    }
    public void setSelectedCategoryList(List<String> selectedCategoryList) {
        this.selectedCategoryList = selectedCategoryList;
    }
    public void generateExam() {
        System.out.println("Chosen categories:");
        for(String cat: selectedCategoryList) {
            System.out.println(cat);
        }
        System.out.println();
        System.out.println("Chosen level: " + candidateLevel);
        System.out.println();
        System.out.println("Chosen candidate: " + selectedCandidateId);
        //examDelegate.generateExam(selectedCategoryList, candidateLevel, selectedCandidateId);
    }
}

The problem I've is that once the form is submitted I only see the values from the last checkbox in my bean property selectedCategoryList. Can someone please tell me how do I collect the values from all the checkboxes? I'm forced to give different Ids for each checkbox because I want to be able to collapse each one of them separately on a button click. I tried changing the bean property selectedCategoryList to be a List<List<String>>. And then on my xhtml page I tried to set the value attribute of my checkbox to be something like

<h:selectManyCheckbox id="checkbox_#{status.index}" value="#{examBean.selectedCategoryList[status.index]}" style="display:none">

It didn't really work, I got an array out of bounds exception for 0. The list was initialized, so not sure how I was getting an array out of bounds exception.

SerotoninChase
  • 424
  • 11
  • 28
  • Using JSTL Core functionality within JSF is not advisable, see http://stackoverflow.com/questions/4154841/mixing-jsf-tags-with-jstl-tags-gives-strange-results for examples. Why don't you try coding this as a h:dataTable (it does the id-numbering for you as well, so no unique-id exceptions anymore)... – L-Ray Dec 18 '13 at 09:33
  • That still doesn't answer my problem. I have changed the implementation to data table. Please see my edited post. I am trying to figure out how I can get the values from all the checkboxes and not just the last checkbox. – SerotoninChase Dec 18 '13 at 18:51

1 Answers1

0

I found a work around. I changed my select many checkbox to the one shown below:

<h:selectManyCheckbox id="checkbox" value="#{cat.selectedCategories}" style="display:none">

And then, I added that property selectedCategories to the child objects, rather than looking for some way to get the selected items at the parent level.

SerotoninChase
  • 424
  • 11
  • 28