0

I have list of h:selectBooleanCheckBox in rich:dataTabe. Also, there is pagination for the datatable.

The problem is when I click the next page number, the selected checkboxes at the first page of the datatable is gone. Though they are selected, clicking the next/previous page make them deselected.

Any idea about the problem?

These are the annotations for bean.

@ManagedBean(name = "bean") 
@ViewScoped

To clarify it, I've attached my facelets and bean code below:

<rich:dataTable  value="#{bean.ssTable}" var="data" iterationStatusVar="it" id="myDataTable">     
    ...
    <rich:column id="includeInWHMapping" >

        <f:facet name="header">
            <h:selectBooleanCheckbox value="#{bean.selectAll}" valueChangeListener="#{bean.selectAllCheckBox}">
                <f:ajax render="myDataTable" />
            </h:selectBooleanCheckbox>  
        </f:facet>      

       <h:selectBooleanCheckbox id="selectedForWHProcess" value="#{bean.checked[data]}">        
            <f:ajax actionListener="#{bean.selectAllRows}" />
       </h:selectBooleanCheckbox>   

    </rich:column>
    ...
</rich:dataTable>

Bean code:

    private Map<StandardStructure, Boolean> checked = new HashMap<StandardStructure, Boolean>();
    private boolean selectAll;

    /* Controller */
    public MyController() {
        super(new DataSetParameters()); 

        logger.info("StandardStructureController created.");

        Column rowid_col =new Column("rowid", "rowid",  "No.", FilterTypes.NUMERIC, true, true, "");
        Column fileid_col =new Column("fileid", "fileid",   "File ID", FilterTypes.STRING, true, true, "");
        Column releasetag_col =new Column("releasetag", "releasetag",   "Releasetag ID", FilterTypes.STRING, true, true, "");
        Column applicationid_col =new Column("applicationid", "applicationid",  "Application ID", FilterTypes.STRING, true, true, "");
        Column filename_col =new Column("filename", "filename", "Filename", FilterTypes.STRING, true, true, "ASC");
        Column includeInWHMapping_col =new Column("includeInWHMapping", "includeInWHMapping",   "Include in WH Mapping?", FilterTypes.NONE, true, true, "");

        columns.put("fileid", fileid_col);
        columns.put("releasetag", releasetag_col);
        columns.put("applicationid", applicationid_col);
        columns.put("filename", filename_col);
        columns.put("includeInWHMapping", includeInWHMapping_col);

        initialize();
        setOrderField("importDate");
        setOrder("DESC");   
        dataSetParameters.setColumns(columns);
        loadTable();
    }

    /** getter/setter.. */
    public boolean isSelectAll() {
        return selectAll;
    }
    public void setSelectAll(boolean selectAll) {
        this.selectAll = selectAll;
    }

    public Map<StandardStructure, Boolean> getChecked() {
        return checked;
    }

    public void setChecked(Map<StandardStructure, Boolean> checked) {
        this.checked = checked;
    }
    /** Load ssTable */
    private void loadTable() {
        try{
            ssTable = new StandardStructureDao(dataSetParameters).getAllStandardStructure();
        }catch (Exception ex){
            System.out.println("Exception in loading table:"+ex);
        }
    }

    /** Get ssTable */
    public Collection<StandardStructure> getSsTable(){  
        return ssTable.getDto();
    }

    /** Pagination */
    public void doPaginationChange(ActionEvent event) {         
        super.doPaginationChange(event);
        loadTable();

        /* trying to set the value of list of checkboxes after loading the table */ 
        Iterator<StandardStructure> keys = checked.keySet().iterator(); 
        while(keys.hasNext()){
            StandardStructure ss = keys.next();
            if(checked.get(ss)){ /* getting checked boxes */
                /* Got stuck here. */ 
               /* How do we just set the true (boolean) value only 
                for list of checkboxes though they are in Map?*/
                System.out.println("Row id: " + ss.getRowid() + " Checked : " + checked.get(ss));       
            }
        }
    }

    /** Select all the list of checkbox in datatable */
    public void selectAllCheckBox(){
        for(StandardStructure item : ssTable.getDto()){
            if(!selectAll)
                checked.put(item, true);
            else
                checked.put(item, false);
        }
    }

    /** Select row of data in datatable */
    public void selectAllRows(ValueChangeEvent e) {
        boolean newSelectAll = (Boolean) e.getNewValue();
        Iterator<StandardStructure> keys = checked.keySet().iterator();
        logger.info("Rows selected..." + newSelectAll);
        while(keys.hasNext()) {
            StandardStructure ss = keys.next();
            checked.put(ss, newSelectAll);
            System.out.println("File::"+ss.getRowid()+":"+newSelectAll);
        }   
    }

Many Thanks!

  • What is `selectAllRows` and why you have this in SINGLE row checkbox? – Emil Sierżęga Aug 31 '16 at 11:40
  • @EmilSierżęga Hey thanks for the reply. Actually you can ignore "selectAllRows" as it select the data of particular row. – Sarthak Joshi Aug 31 '16 at 12:06
  • 1
    I just highly doubt it that "Though they are selected". What is the value for the table? Is it a list or lazy loaded data model? In xhtml you use `ssTable` in for loop `ssTable.getDto()`. – Emil Sierżęga Aug 31 '16 at 12:22
  • @EmilSierżęga "selectAllRows" saves the data into Map. I am using Collection for datatable. Thats why I used ssTable.getDto(). – Sarthak Joshi Aug 31 '16 at 14:53
  • @EmilSierżęga Hey I have added some more codes in bean to make it more clear. Thanks! :) – Sarthak Joshi Sep 01 '16 at 03:39
  • Like I said, `selectAllCheckBox` and `selectAllRows` does exactly the same (the result with `checked` is the same) and one is for global select all and the second we "can ignore". Can you show us the initialization of checked? – Emil Sierżęga Sep 01 '16 at 07:51
  • @EmilSierżęga Yeah you are correct! You can ignore the second one. And what kind of initialization of checked are you asking? I have added getter and setter for checked property. – Sarthak Joshi Sep 01 '16 at 08:06
  • Constructor, @PostConstruct etc... – Kukeltje Sep 01 '16 at 08:31
  • @EmilSierżęga I have added the Initialization too. Please do check. – Sarthak Joshi Sep 01 '16 at 08:39
  • You creating new ssTable with every page change, how do you expecting it to work without any proper initialization of `checked`? Also I've asked if you getting all values (ALL which means that you have i.e. list of 105 object, but you are displaying 20 of them at one time) or if it's some kind of data model. It looks like data model or you are really don't know what you are doing – Emil Sierżęga Sep 01 '16 at 08:40
  • @EmilSierżęga Actually the Query only fetch 10 rows at a time, likewise there are 10 rows in dataTable in each page. This is done to make efficient loading. Also when I do the pagination the whole page does not reload, only "loadTable method" is called by "doPaginationChange". What do you mean by proper initialization of checked? Im sorry I did not get you. And the main concern here is, I can check all the checkbox at once but once I hit "Next page" of the dataTable, those checked boxes are dis-selected. Thanks. – Sarthak Joshi Sep 01 '16 at 08:51
  • For now, your `selectAll` works like select all from current page. – Emil Sierżęga Sep 01 '16 at 09:07
  • @EmilSierżęga Yeah it does. But rest list of checkboxes does not remains checked after pagination. Only the header check box remains checked. What might be the problem? Thanks! – Sarthak Joshi Sep 01 '16 at 09:12
  • And you want that to work as select all on current page? – Emil Sierżęga Sep 01 '16 at 09:13
  • @EmilSierżęga Yeah, I want the list of checkboxes remain checked even after the pagination in current page. Thanks. – Sarthak Joshi Sep 01 '16 at 09:14
  • @EmilSierżęga Please help me! :) – Sarthak Joshi Sep 01 '16 at 09:27
  • @EmilSierżęga Hey there. I'm trying different approach. I tried to retian the state of list of checked boxes after the pagination. But I unable to set the value (true) of them. Please do check "doPaginationChange(ActionEvent event)" in above bean code. I think you will get what I'm trying to do. Thank you. – Sarthak Joshi Sep 02 '16 at 09:24

1 Answers1

1

Since your code is unclear and confusing, I'll provide you the minimal example how pagination with select all on current page MIGHT look like. With no action listeners, just getters and setter. As simple as I could.

First XHTML:

<h:form>
    <rich:dataTable value="#{bean.valuesOnPage}" var="data" id="dataTable" rows="20">
        <rich:column>
            <f:facet name="header">
                <h:selectBooleanCheckbox value="#{bean.selectAll}">
                    <f:ajax render="dataTable" />
                </h:selectBooleanCheckbox>
            </f:facet>
            <h:selectBooleanCheckbox value="#{bean.checked[data]}">
                <f:ajax />
            </h:selectBooleanCheckbox>
        </rich:column>

        <!-- other columns -->
    </rich:dataTable>
</h:form>

Then the bean:

@ManagedBean(name = "bean")
@ViewScoped
public class MyBean {

    // when the view is first loaded this is empty
    // until someone will click one of checkboxes
    private Map<Object, Boolean> checked = new HashMap<Object, Boolean>();
    private boolean selectAll;

    private List<Object> valuesOnPage;
    private int currentPage = -1;

    MyBean() {
        setCurrentPage(1);
    }

    // no setter
    public Map<Object, Boolean> getChecked() {
        return checked;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public boolean getSelectAll() {
        return selectAll;
    }

    // no setter
    public List<Object> getValuesOnPage() {
        return valuesOnPage;
    }

    private void loadTable() {
        try {
            // gets data from data base
            valuesOnPage = getData(currentPage);
        } catch (Exception ex) {
            System.out.println("Exception in loading table:" + ex);
        }
    }

    public void setCurrentPage(int currentPage) {
        if (this.currentPage != currentPage) {
            this.currentPage = currentPage;
            loadTable();
            // we don't need it selected, especially if it
            // was a paged we've never been on
            selectAll = false;
        }
    }

    public void setSelectAll(boolean selectAll) {
        this.selectAll = selectAll;
        for (Object o : valuesOnPage) {
            checked.put(o, selectAll);
        }
    }
}

Look how and when the data is changing and when it is loaded. Check out that there's no unnessecary new action for checkbox of single row. JSF will take care of that with: value="#{bean.checked[data]}".

And once again: Your keys in map are objects. You have to make sure that equals method is good. In 95% of case the default is not, especially if they are @Entity. Check i.e. this topic.

Community
  • 1
  • 1
Emil Sierżęga
  • 1,785
  • 2
  • 31
  • 38
  • Thank you Emil. I will check it out. Will let you know! :) – Sarthak Joshi Sep 01 '16 at 10:57
  • What do you mean by "You have to make sure that equals method is good." ? I did not get it. Yeah Keys in map are object and yes they are Entity. By the way its working working. :/ Thanks for your effort anyway! :) – Sarthak Joshi Sep 01 '16 at 11:34
  • BTW it is working. I've checked it ;-) Just use Ids of entities in map, not object. – Emil Sierżęga Sep 01 '16 at 11:51
  • Really? How do you use ids of entities in map? I need objects in map to select them to process later. How can I use ids? Im confused. – Sarthak Joshi Sep 01 '16 at 12:02
  • Man, you are killing me. Did you use debug? Did you check what is in `checked`? Probably there is a lot of garbage, because when you are changing the page use are changing objects INSTANCES. Get first object from list, change the page, return to the 1st and check if they are equal. If you're using i.e. Hibernate and this object has lazy loaded dependencies, then they are probably NOT equal if you are not using business key. I've added one link to my answer... – Emil Sierżęga Sep 01 '16 at 12:12
  • No, still having same problem. :/ – Sarthak Joshi Sep 02 '16 at 04:25
  • Well then, there's nothing I can do. Like I said: I provided you the working code which you can adapt to your situation. I'm sorry if that is not enough. – Emil Sierżęga Sep 02 '16 at 10:02
  • Hey there. I'm trying different approach. I tried to retian the state of list of checked boxes after the pagination. But I unable to set the value (true) of them. Please do check "doPaginationChange(ActionEvent event)" in above bean code. I think you will get what I'm trying to do. Thank you. – Sarthak Joshi Sep 02 '16 at 11:01