Friday, August 10, 2012

Implementing Select One ,Select None and getting Selected row in Backing Bean of af:table

Hi,

I came across one common  use case where we need to have select all ,select none and also we need to get selected rows into backing bean which later we want to perform operation on select records of af table.
Following use case are also part of the same use case.

1->User want to delete selected rows at a time.
2->User want to update selected rows at a time.i.e. approve or reject.
3->Delete all the rows at once.

Even though you can find allot of solution of this problem on internet but they contains allot of java code.But in my solution i try to minimizing the  java code   .

I have divided my way of implemention  approach following part.

1-Since we require check box for selecting the rows .So for creating the check box at model layer is first part.
2-Getting the selected row into the backing bean is second part.
3-Selecting or deselecting all rows at once in af:table is third part .


1-Creating the check box in af:table :

We can use ADF BC as model layer or EJB 3.0 .Here i have been used the EJB 3.0 hence i am going to first explain though EJB 3.0.

Steps are following :


1-Create the  enitiy bean from table using Employee table.
2-Then i have added one attribute name as checkBox  as Boolean type .
    code are  following
    @Transient
    private Boolean checkBox;
3-Make this attribute as  @Transient and create the setter and  getter of the checkBox.
4- Create the Session bean and then data control.
5-Go to the Employee.xml file which has been created after data control .Select checkBox attribute and click the edit button and select controls hints and change the control type value default to check box.(By doing this when we drag and drop the table in jspx page the checkbox automatically come as check box).
6-Drag and drap the employeeFindAll method which has been created automatically when you create the data control .Moreover this method will return the all employee value list from the data.Since i need to show the af:table on ui so i am going to drag and drop this method as af:table (do not select af:table read only because check box should be editable.later you can make other columns read only on basis of requirment)

"If you are using ADF BC as model layer then  you just need  to do the same thing in the VO,it mean  add one transient attribute and later change it to check box same thinks which i did in EJB"

The first step has been finished.Our jspx page is ready with one af:table where we have first column as select check .


2-Getting the selected row into the backing bean:

I have created the value change listener of select one choice where  i am check whether the select box is selected or not .


    public void valueChangeListener(ValueChangeEvent valueChangeEvent) {
        Boolean value = (Boolean)valueChangeEvent.getNewValue();
        Row exmapleObject =
            (Row)evaluateEL("#{bindings.employeeFindAll.currentRow}");
        AdfFacesContext context = AdfFacesContext.getCurrentInstance();
        Set list = null;
        if (value) {
            Object object = context.getPageFlowScope().get("selectedRows");
            if (object == null) {
                list = new HashSet();
                context.getPageFlowScope().put("selectedRows", list);
            }
            Set adding = (Set)context.getPageFlowScope().get("selectedRows");
            adding.add(exmapleObject.getAttribute("employeeId"));
            context.getPageFlowScope().put("selectedRows", adding);
        } else {
            Set removing = (Set)context.getPageFlowScope().get("selectedRows");
            removing.remove(exmapleObject.getAttribute("employeeId"));
        }
    }

3-Selecting or deselecting rows at once in af:table:

selectAllRowButton is responsible for making all the rows selected and deSelectAllRowButton is for deselection the row,



    public void selectAllRowButton(ActionEvent actionEvent) {
        AdfFacesContext context = AdfFacesContext.getCurrentInstance();
        Set list = null;
        Object object = context.getPageFlowScope().get("selectedRows");
        if (object == null) {
            list = new HashSet();
            context.getPageFlowScope().put("selectedRows", list);
        }
        Set adding = (Set)context.getPageFlowScope().get("selectedRows");
        RowSetIterator rowSet = getTableIterator();
        while (rowSet.hasNext()) {
            Row row = rowSet.next();
            row.setAttribute("checkBox", Boolean.TRUE);
            adding.add(row.getAttribute("employeeId"));
        }
        rowSet.closeRowSetIterator();
        context.getPageFlowScope().put("selectedRows", adding);
        AdfFacesContext.getCurrentInstance().addPartialTarget(tableBinding);
    }

    public void deSelectAllRoButton(ActionEvent actionEvent) {
        AdfFacesContext context = AdfFacesContext.getCurrentInstance();
        Set list = null;
        Object object = context.getPageFlowScope().get("selectedRows");
        if (object == null) {
            list = new HashSet();
            context.getPageFlowScope().put("selectedRows", list);
        }
        Set removing = (Set)context.getPageFlowScope().get("selectedRows");
        RowSetIterator rowSet = getTableIterator();
        while (rowSet.hasNext()) {
            Row row = rowSet.next();
            row.setAttribute("checkBox", Boolean.FALSE);
            removing.remove(row.getAttribute("employeeId"));
        }
        rowSet.closeRowSetIterator();
        context.getPageFlowScope().put("selectedRows", removing);
        AdfFacesContext.getCurrentInstance().addPartialTarget(tableBinding);
    }


* One point which i would like to share here that is  in all three method i am setting the selected employee id value into page flow scope.

Here i am first checking  a variable that  is the variable is present in page flow scope or not.if it is null i page flow first i created the new instance of the Set and adding into the page flow scope .If the user clicked on the any check box of the table first i am getting the selected row and adding  the value in the set which is present in page flow and after adding value into set i am again putting the value in page flow scope.

And if the user deselected the check box then i am again the getting the value from page flow and removing from the set and again adding into the page flow .

Although i explained model layered as EJB 3.0 but from the data controls till  UI the approach would be same  in ADF BC.


Project source code is available on following url

http://www.4shared.com/rar/etlDbINh/SelectAllAndNone.html


Thanks
Prateek

4 comments:

  1. Dude Why do you need a transient attribute from the model layer. You are handling everything on the UI i.e using pageFlowScope Map. You can very well add a column with checkbox. Just have a Map which is initialized with the number of rows present (getEstimatedRowCount on the table)when the page is rendered and set it in pageFlowScope. The Map will take rowIndex as the key and the boolean selection as value. Provide the checkbox value as #{pageFlowScope.urMap[rowIndex.index]}, where rowIndex is the varStatus value on table. This way you need not have a value change listener.
    For Select All & De Select All have two methods defined which will iterate over the Map and set the values to true or false. And a partialTarget on the table and it will show you all selected/deselected.

    Thanks,
    Rakesh

    ReplyDelete
    Replies
    1. Hi ,
      Rakesh I agreed what you has written.But here we also need to get the selected rows as well.means regardless select and deselect features we also need to have to get selected rows at a time.That is reason why i used value change listener.

      Delete
    2. You get the selected rows from getSelectedRowKeys and just add an extra if condition to check if the corresponding rowindex in Map is selected.
      Anyways as you mentioned there are different ways to approach a problem. If you have the flexibility to do modification to the EJB code, you can very well go with your approach. But sometimes you do not get that handle as some other team might design the EJB and you have to handle it in UI so in that case my approach is more relevant.

      Thanks,
      Rakesh

      Delete
    3. Thanks for your valuable information.Yes i agreed your point.

      Delete