Please disable your adblock and script blockers to view this page

Search this blog

Monday 1 May 2017

Undo row selection of af:table in selection listener method conditionally


Recently I have seen a question on OTN Jdeveloper forum and It was about table selection listener
Requirement is like this suppose user has to check a condition after selecting a row and if that condition is true only then new row will be selected else selected row should be previous one

It means undo row selection on validation(condition) failure
So In this post I am implementing same scenario and here I am using Departments table of HR Schema to prepare model and condition is that user should be able to select new row only if ManagerId is not null



Drop Departments view object on page as af:table and create a custom selection listener in managed bean

<af:table value="#{bindings.DepartmentsVO1.collectionModel}" var="row"
                          rows="#{bindings.DepartmentsVO1.rangeSize}"
                          emptyText="#{bindings.DepartmentsVO1.viewable ? 'No data to display.' : 'Access Denied.'}"
                          rowBandingInterval="0"
                          selectedRowKeys="#{bindings.DepartmentsVO1.collectionModel.selectedRow}" rowSelection="single"
                          fetchSize="#{bindings.DepartmentsVO1.rangeSize}"
                          filterModel="#{bindings.DepartmentsVO1Query.queryDescriptor}"
                          queryListener="#{bindings.DepartmentsVO1Query.processQuery}" filterVisible="true"
                          varStatus="vs" id="t1" autoHeightRows="10" styleClass="AFStretchWidth"
                          contentDelivery="immediate"
                          selectionListener="#{viewScope.TableSelectionBean.tableSelectionListener}">
                    <af:column sortProperty="#{bindings.DepartmentsVO1.hints.DepartmentId.name}" filterable="true"
                               sortable="true" headerText="#{bindings.DepartmentsVO1.hints.DepartmentId.label}" id="c1">
                        <af:outputText value="#{row.DepartmentId}"
                                       shortDesc="#{bindings.DepartmentsVO1.hints.DepartmentId.tooltip}" id="ot1">
                            <af:convertNumber groupingUsed="false"
                                              pattern="#{bindings.DepartmentsVO1.hints.DepartmentId.format}"/>
                        </af:outputText>
                    </af:column>
                    <af:column sortProperty="#{bindings.DepartmentsVO1.hints.DepartmentName.name}" filterable="true"
                               sortable="true" headerText="#{bindings.DepartmentsVO1.hints.DepartmentName.label}"
                               id="c2">
                        <af:outputText value="#{row.DepartmentName}"
                                       shortDesc="#{bindings.DepartmentsVO1.hints.DepartmentName.tooltip}" id="ot2"/>
                    </af:column>
                    <af:column sortProperty="#{bindings.DepartmentsVO1.hints.ManagerId.name}" filterable="true"
                               sortable="true" headerText="#{bindings.DepartmentsVO1.hints.ManagerId.label}" id="c3">
                        <af:outputText value="#{row.ManagerId}"
                                       shortDesc="#{bindings.DepartmentsVO1.hints.ManagerId.tooltip}" id="ot3">
                            <af:convertNumber groupingUsed="false"
                                              pattern="#{bindings.DepartmentsVO1.hints.ManagerId.format}"/>
                        </af:outputText>
                    </af:column>
                    <af:column sortProperty="#{bindings.DepartmentsVO1.hints.LocationId.name}" filterable="true"
                               sortable="true" headerText="#{bindings.DepartmentsVO1.hints.LocationId.label}" id="c4">
                        <af:outputText value="#{row.LocationId}"
                                       shortDesc="#{bindings.DepartmentsVO1.hints.LocationId.tooltip}" id="ot4">
                            <af:convertNumber groupingUsed="false"
                                              pattern="#{bindings.DepartmentsVO1.hints.LocationId.format}"/>
                        </af:outputText>
                    </af:column>
                </af:table>

Now next step is implementing SelectionListener code so for that logic is simple

  • First We need to get currently selected row key (Old Row)
  • Set newly selected row as current row
  • Now get current row (new row) and check that ManagerId should not be null
  • If it is null then set prevous row as current row

Packages Used


import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.ValueExpression;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import oracle.adf.view.rich.component.rich.data.RichTable;
import oracle.adf.view.rich.context.AdfFacesContext;

import oracle.jbo.Row;

import org.apache.myfaces.trinidad.event.SelectionEvent;
import org.apache.myfaces.trinidad.model.RowKeySet;


Helper Methods


    /**
     * Programmatic invocation of a method that an EL evaluates to.
     * The method must not take any parameters.
     *
     * @param el EL of the method to invoke
     * @return Object that the method returns
     */
    public static Object invokeEL(String el) {
        return invokeEL(el, new Class[0], new Object[0]);
    }

    /**
     * Programmatic invocation of a method that an EL evaluates to.
     *
     * @param el EL of the method to invoke
     * @param paramTypes Array of Class defining the types of the parameters
     * @param params Array of Object defining the values of the parametrs
     * @return Object that the method returns
     */
    public static Object invokeEL(String el, Class[] paramTypes, Object[] params) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ELContext elContext = facesContext.getELContext();
        ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
        MethodExpression exp = expressionFactory.createMethodExpression(elContext, el, Object.class, paramTypes);
        return exp.invoke(elContext, params);
    }

    /**
     * Programmatic evaluation of EL.
     * @param el EL to evaluate
     * @return Result of the evaluation
     */
    public static Object evaluateEL(String el) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ELContext elContext = facesContext.getELContext();
        ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
        ValueExpression exp = expressionFactory.createValueExpression(elContext, el, Object.class);
        return exp.getValue(elContext);
    }

SelectionListener of af:table


    /**Method to invoke custom selection listener
     * @param selectionEvent
     */
    public void tableSelectionListener(SelectionEvent selectionEvent) {
        //Get previous selected row key
        RowKeySet oldRowKey = selectionEvent.getRemovedSet();
        //Get Richtable instance fron selectionEvent
        RichTable table = (RichTable) selectionEvent.getSource();
        //Invoke this EL to make selected row as current
        invokeEL("#{bindings.DepartmentsVO1.collectionModel.makeCurrent}", new Class[] { SelectionEvent.class }, new Object[] {
                 selectionEvent });
        // Get the selected row , by this you can get any attribute of that row
        Row selectedRow = (Row) evaluateEL("#{bindings.DepartmentsVO1Iterator.currentRow}");
        System.out.println("Selected Deaprtment is- " + selectedRow.getAttribute("DepartmentName"));
        //Now check condition that Manager Id should not be null for newly selected row
        if (selectedRow.getAttribute("ManagerId") == null) {
            //If Manager Id is null then set focus on previously selected row and show a message to user
            table.setSelectedRowKeys(oldRowKey);
            //Refresh table
            AdfFacesContext.getCurrentInstance().addPartialTarget(table);
            //Show FacesMessage
            FacesContext fctx = FacesContext.getCurrentInstance();
            fctx.addMessage(null, new FacesMessage("Can't Select new row as Manager Id is null"));
            //Save and render response
            fctx.renderResponse();
        }
    }

Now run and check application


Try to select Departmentthat has no manager

Undo row selection on selection listener

Cheers :) Happy Learning

3 comments :

  1. Working like a charm
    Thanks

    ReplyDelete
  2. I Was looking for this

    Thanks a lot Ashish

    ReplyDelete
  3. Hello sir, I'm Chandan and I follow your blog and on Quora..The contents you post are very useful.
    After around two months of preparation I took 1z0-554 certification but I couldn't clear it.anyhow I'm again taking the exam.
    I've some set of questions which I'm trying to find answers that appeared in the exam.
    If possible please give me your mail id and I'll send the questions.if you give me the solutions for it, It'll be very useful..My mail id chandanhs77@gmail.com

    ReplyDelete