ADF 11g Rich Faces: focus on field after button press or PPR – Including JavaScript in PPR response and ClientListeners (Client Side programming in ADF Faces Rich Client Components Part 2)

2

In this second part of a series on ADF 11g Rich Faces Client Programming, I will talk about the option to include JavaScript in a PPR response, to execute on the client once the processing of the PPR response is complete. There can be several good reasons for such client side operations, such as:

  • setting the focus on a particular field on the page
  • scrolling the page or a DIV or other container element to a specific position
  • refreshing non-data bound items
  • etc.

Inside (managed bean) code that is executed during a partial page rendering request/response cycle, we can specify JavaScript code that should be executed in the browser once the PPR response has been absorbed by the client.

A very trivial example of what we can do is shown here:

When the Name field is updated, it autoSubmits. The managed bean that is associated with the value of Name adds a little JavaScript to the PPR response. This JavaScript set the shortDesc property of the Name component on the client – using the ADF Faces 11g JavaScript API.

The code for this looks as follows:

          <af:inputText label="Name" id="inputText1" autoSubmit="true"
                          value="#{backing_setFocus.value}"
          />

the Name input element; note no value is set for the shortDesc attribute. AutoSubmit is set to true. Value is bound to a managed bean property.

The managed bean contains the setValue() method that has been defined like this:

    public void setValue(String newvalue) {
        this.value = newvalue;
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExtendedRenderKitService service =
        (ExtendedRenderKitService)Service.getRenderKitService(facesContext,
        ExtendedRenderKitService.class);
        service.addScript(facesContext,
                          " var b = AdfPage.PAGE.findComponent('inputText1' );
                            b.setShortDesc('value is "+newvalue+" as of "+new Date()+"'); ");

    }

Using the ExtendedRenderKitService, you can add JavaScript to a response, after invoking an action method binding or performing a PPR cycle. You see here how I have added script to the service that uses the ADF RichFaces JavaScript API to locate the component with id equals inputText1. When it has the component, of type AdfRichInputText. Then we use the API for that object to set the shortDesc property.

 

Setting focus to a particular field – after performing some action

 

I first ran into the ExtendedRederKitService as a means to add JavaScript to the PPR response when I tried to respond to a question on the JDeveloper 11g Discussion Forum on OTN. The question was:

hi

i have two af:inputText and a command button in my page.
when the page is loaded i want the cursor to be in the first textbox and when i click a button the cursor should be focused to the next input text.

how to do this??
plz help me.

 

And this  got me thinking: how can you set the focus on a field in the browser window in the first place and how can you make that that happens after you have pressed a button that performs a server side action. Setting focus on a field is done in JavaScript, something like:

      function setFocusId(id) {
        var t=document.getElementById(id);
        t.focus();
      }

Now the question is: how can I trigger this code to execute at the right time. There are at least two solutions: one will execute just prior to invoking the server and one will execute after server side processing is complete and the PPR response has been absorbed. A third solution is client side only – which probably is not very useful in most circumstances.

My page looks like this:

Any of these buttons will put focus on the ID field. They do it at different times in slight different ways. The first button uses the piggyback Client Script on PPR response, that we also saw in the first section of this article:

        <af:commandButton text="Execute actionListener and set focus on ID" id="commandButton1"
                          actionListener="#{backing_setFocus.commandButton1}"/>

The backing bean has the commandButton1 method that acts as actionListener. This method could do lots of useful server side stuff, and then concludes with adding the JavaScript code that will upon return to the client transfer focus to the inputText2 item:

    public void commandButton1(ActionEvent actionEvent) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExtendedRenderKitService service =
        (ExtendedRenderKitService)Service.getRenderKitService(facesContext,
        ExtendedRenderKitService.class);
        UIComponent ip = facesContext.getViewRoot().findComponent("inputText2");
        String clientId = ip.getClientId(facesContext);
        service.addScript(facesContext,
                          "setFocusId('"+clientId+"::content');");
    }

The second button uses a clientListener that intercepts the button press, performs a client side function and then makes way to normal client-server processing of the button press event:

        <af:commandButton text="Do a partial submit and set focus on ID" id="commandButton3"
                          partialSubmit="true">
          <af:clientListener method="setFocus" type="action"/>
        </af:commandButton>

It relies on a JavaScript function included in the page:

    <af:document >
      <trh:script text="

      function setFocus(event) {
         setFocusId('inputText2::content');
      }

      function setFocusId(id) {
        var t=document.getElementById(id);
        t.focus();
      }

    function setFocusNoPropagate(event) {
      setFocus(event);
      event.cancel();
    }
"/>
      <af:form id="form1">

The third button also has a clientListener, that will set focus to the inputText2 item. However, the setFocusNoPropagate function then calls cancel() on the event, meaning that its processing should stop immediately. That means that the form will not be submitted to the server, nor will any server side logic be invoked.

      <af:commandButton text="Set focus on ID" id="commandButton8">
        <af:clientListener method="setFocusNoPropagate" type="action"/>
      </af:commandButton>

This is not part in any way of the button; it is in the client side function called from the clientListener.

 

Resources

The ADF 11g Rich Faces JavaScript API.

The ADF Faces 11g Web UI Developer Guide

Part 1 in this series:  Client Side programming in ADF Faces Rich Client Components

 

Share.

About Author

Lucas Jellema, active in IT (and with Oracle) since 1994. Oracle ACE Director for Fusion Middleware. Consultant, trainer and instructor on diverse areas including Oracle Database (SQL & PLSQL), Service Oriented Architecture, BPM, ADF, Java in various shapes and forms and many other things. Author of the Oracle Press book: Oracle SOA Suite 11g Handbook. Frequent presenter on conferences such as JavaOne, Oracle OpenWorld, ODTUG Kaleidoscope, Devoxx and OBUG. Presenter for Oracle University Celebrity specials.

2 Comments

  1. Hi,

    I used code @ http://manieshsailoz.blogspot.com/2010/04/how-to-set-focus-using-javascript-and.html for setting focus on a component after tab out & it works fine.

    In my second usecase I have around 20 inputText field & one single valuechangelistener for all. In this listener based on certain condition I want to throw exception & after exception want to highlight the field which caused the exception. What I observe using above code is the focus is moved to next component as I tab out. If I don’t throw the exception then the setFocus is working fine. Its only after throwing exception the focus is not set correctly.

    Any suggestions ?

    Thanks,
    Bhargav

  2. The method:
    public void commandButton1(ActionEvent actionEvent) {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExtendedRenderKitService service =
    (ExtendedRenderKitService)Service.getRenderKitService(facesContext,
    ExtendedRenderKitService.class);
    UIComponent ip = facesContext.getViewRoot().findComponent(“inputText2″);
    String clientId = ip.getClientId(facesContext);
    service.addScript(facesContext,
    “setFocusId(‘”+clientId+”::content’);”);
    }
    work ok.
    Thank.