29 November 2011

APEX: Make a report row clickable in Report

When you create a "Report with Form", there will be an icon in the report which allows you to navigate to  the form page. Only when the user clicks the icon this navigation will take place. For the current project, this was not what they wanted. They wanted to click on the row instead of just the icon. This can be simply implemented using jQuery.
For this example we are going to use a "Report with Form" and modify it as described below.
All of our pages in the application have a page alias, the Report page alias is "EMP001" and the Form page has an alias "EMP002".
The default behaviour will appear in the page like the below screenshot, the cursor will turn into a small hand only when you move your mouse over the icon.

But we want to achieve the following: moving the cursor over the whole row changes the cursor to a small hand  indicating that the whole row is clickable. And not only that, also that the whole row is in fact clickable.
To achieve this we would need to "move" (or copy) the anchor to row-level.

When you look at the generated HTML code, it will look something similar to this:
The highlighted line in the picture is the icon which is shown in the Report page (alias: EMP001). As you can see in the image, the anchor (the "a" tag) has an href attribute which contains all the information it needs to navigate to the Form page (alias: EMP002). Even the page alias is in there, and this is what we will use to select the correct href.
Because the page alias is in the anchor, we can use the jQuery selector to get the appropriate element

$('a[href*="EMP002"]')

This will result in an array of anchor elements which we want to manipulate. For each of the elements in the array we want to retrieve the href attribute. The href attribute, we will keep in a local variable named "lnk". Now the code will look like:
$('a[href*="EMP002"]').each(function(index) { 
    lnk = $(this).attr('href');

});


This variable with the href attribute is going to be place at row level as a "data-href". From the current element we need to move up to the row level (tr) and add the attribute.

   $(this).parent()
          .parent('tr')
    .attr('data-href', lnk)

To make it clickable, we also need to add a click event to the row. This is where jQuery really shows its power, we can "chain" the click event to our selector. The code will grow slightly to the following:

 $(this).parent()
          .parent('tr')
    .attr('data-href', lnk)
    .click(function(){
      window.location=$(this).attr('data-href');
    })

To give the user the feedback that the row is clickable, we need to change the cursor to a little hand. Again we chain the mouseover event to the selector

$(this).parent()
          .parent('tr')
    .attr('data-href', lnk)
    .click(function(){
      window.location=$(this).attr('data-href');
    })
    .mouseover(function(){
      $(this).css('cursor', 'pointer');
    })

And because we also want to change the cursor back to default when the user move the cursor away from the rows in the report, the mouseleave event is also required

   $(this).parent()
          .parent('tr')
    .attr('data-href', lnk)
    .click(function(){
      window.location=$(this).attr('data-href');
    })
    .mouseover(function(){
      $(this).css('cursor', 'pointer');
    })
    .mouseleave(function(){
      $(this).css('cursor', 'default');
    })
Now that the jQuery code is complete, we can add this to the page
Double click at page level to open the page properties, and paste the jQuery code in the section labelled "Execute when Page Loads" and we are all set.


When you run the page you will notice that the whole row is clickable.
Inspecting the HTML after we add all the jQuery code will show that there is an anchor at the row level now, just what we wanted.

To make copy the code for your own use, the completed jQuery code will look like this
$('a[href*="EMP002"]').each(function(index) {
   lnk = $(this).attr('href');
   $(this).parent()
          .parent('tr')
    .attr('data-href', lnk)
    .click(function(){
      window.location=$(this).attr('data-href');
    })
    .mouseover(function(){
      $(this).css('cursor', 'pointer');
    })
    .mouseleave(function(){
      $(this).css('cursor', 'default');
    })
});
And to see this in action you can find a demo on apex.oracle.com

16 comments:

  1. Very nice. See and learn jQuery in practice.

    What would be incredibly nice is also have the row hightlighted.
    Any idea how to incorporate that in the above solution?

    gr. Bart

    ReplyDelete
  2. Hi Bart,
    This is one way to highlight the row on when you move the mouse (which can be done with CSS):
    My report rows have a class attached called "highlight-row" (this can be seen in the screenshot of the generated HTML)
    At page level, place this CSS style in the section called HTML Header:

    <style type="text/css">
    tr.highlight-row:hover td
    {
    background-color: #d12421 !important;
    color: #ffffff;
    }
    </style>

    A better way is to place this CSS in the appropriate CSS file.

    Hope this helps.

    Alex

    ReplyDelete
    Replies
    1. Hi, Alex.

      I was searching the web for a way to highlight a row in a classical or Interactive report on my Apex 4.1 page and then stumbled across this post.

      I really like the way you clearly explained, step-by-step, how to use JQuery selectors to make an entire report row "clickable". That is so cool and useful.

      I also see your suggestion on how to highlight a row using css. I tried out your code and it works great.

      However, I need a way to keep the report row highlighted as users navigate to other regions on the same page. The highlighted row serves as "context" to tell users which row is the currently "active" row.

      Would you know how to accomplish this and, simultaneously, make this highlighted row "clickable".

      Thank you for any help.

      FYI: When I click the "Reply" link on this blog using IE9.x, nothing happens. I had to open the blog in Firefox 15.x in order to get this "Reply" dialogue box to appear.

      Thanks, again.

      Elie

      Delete
    2. Hi Elie,
      Thank you for your nice comments.
      Yes, it's possible to keep the highlighted row as context. See an example here: http://apex.oracle.com/pls/apex/f?p=47888:EMP09:0::NO::

      1) Create a hidden item to store the clicked EMPNO
      2) Add the following javascript code at page level:
      $(function(){
      clicked_empno = $("#P9_EMPNO").val(); $('a[href$="P9_EMPNO:'+clicked_empno+'"]').parent().parent().children().addClass('highlight-employee') ;
      });
      This will add css classes (named highlight-employee) to all elements for the value stored in the hidden item
      3) Add a CSS rule to do the actual highlighting: .highlight-employee{background-color: blue !important;}
      4) In the link (column level), set the value for the hidden item

      Well, IE... what can I say :)
      Alex

      Delete
    3. Wasn't sure if the steps above was enough information that I decided to write a short note about it: http://nuijten.blogspot.nl/2013/01/apex-highlight-record-in-report.html

      Delete
  3. Hi,
    Its a good post however i have two links that open different pages howcan i accomplish this. thanks

    ReplyDelete
    Replies
    1. Hi Anonymous,

      The big question is: how do want it to work? How do you decide which link to open?

      Alex

      Delete
  4. nice post...it's what I'm looking for...
    but when I applied it to my application, it didn't work...
    I copied the jQuery code, then put it in 'Execute when Page loads' field with FORM09 as my form page.but nothing happen...
    can u tell me where is my mistake?

    thanks....
    Zee

    ReplyDelete
    Replies
    1. It's is quite hard to comment on where you made a mistake without being able to look "over your shoulder". There are many possibilities causing it "not to work". When you use a modern browser you might want to look what is going on "behind the scenes". In Firefox or Chrome you can use F12 to detect any errors in the console window.
      Is this application in a place where I can access it, like on apex.oracle.com? If that is the case, you might drop me an email and I'm willing to take a look at the way you implemented it.

      Delete
    2. the problem is solved. :)
      I changed :
      $('a[href*="FORM09"]')
      with :
      $('a[href*="9"]')
      where 9 is the page number, not an alias...

      thank you...

      Zee

      Delete
  5. Hey!
    Great code and it works, until you use pagination to go to page 2 in your report.
    Any suggestions?

    Thanks in advance!

    Yvonne

    ReplyDelete
    Replies
    1. Ah yes, good point... this is what you can do (not saying it's the best way, but... )
      1) move the code that's in the "Execute when Page Load" section to the "Function and Global Variable Declaration" section
      2) before the code add: function rowClick(){
      3) after the code add: }
      With steps 2 and 3 you create a function which can be used (almost) everywhere.
      4) in the "Execute when Page Load" section add: rowClick();
      That's the name of the function created in steps 2 and 3
      5) add a Dynamic Action (Advanced type)
      Event: After Refresh
      Selection Type: Region
      Region: Employees
      True Action: Execute Javascript Code
      Code: rowClick();

      That should do it.

      Delete
    2. Not yet working :(

      We're working on it.
      Maybe it's because we use an Javascript call as our link..?
      $('a[href*="ShowDetail"]')

      Delete
    3. The jQuery that you post is the selector, not a link. This selector means: find me all anchors which have ShowDetail in the link somewhere. The way I used the selector is to find the page-alias (which would be ShowDetail in your case).

      I created a new page, as described in my earlier reply: http://apex.oracle.com/pls/apex/f?p=47888:10:330414103723501:::::
      check it out, using Firebug or Chrome..

      Delete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Works like a charm.
    The only thing I needed to do was change the page-alias (EMP002)

    ReplyDelete