Refreshing Apex Reports Via PPR

In order to do this you need one piece of critical information, the region’s internal id, or the “page plug id” as it is called in the FLOWS (the internal APEX tables). There are a few ways to get this, one way is via the region/report templates using the #REGION_ID# replacement string. In your region template you could include a link along the following lines:

	<a href="javascript:refreshRegion( '#REGION_ID#' );">Refresh</a>

You could of course use a nifty little image, but a link is probably good enough to get started. The most interesting thing about #REGION_ID# is that it is replaced with a string that looks like this: ‘R1234324232332′. The ‘R’ is appended to the beginning for some reason. I can only assume it was either to delineate that the id is actually for a region or that the id’s are only unique to regions and thus the ‘R’ makes the id a UUID (universally unique id). If you want you can find more informational goodies about your regions in the following table: FLOWS_SCHEMA_NAME.wwv_flow_page_plugs -or- if you are using the default APEX 3.0 schema name flows_030000.wwv_flow_page_plugs.

The next thing we need to do is define the JavaScript function call in that link, refreshRegion.

function refreshRegion( regionId )
{
    var regionElement = document.getElementById( regionId );
    if( regionId )
    {
        //obtain our session id so APEX doesn't show us the login page/404
        var sessionId = document.getElementById( 'pInstance' ).value;
 
        //our current application.
        var appId = document.getElementById( 'pFlowId' ).value;
 
        //this could be any page as long as it is defined.
        var pageId = document.getElementById( 'pFlowStepId' ).value;;
 
        html_PPR_Report_Page( regionElement,regionId,'f?p='+ appId +':'+ pageId +':' + sessionId + ':FLOW_PPR_OUTPUT_' + regionId  + '::RP&amp;fsp_region_id='+ regionId );
    }
}

Thats it! In truth this could almost be a one liner, but this ways is cleaner and easier to read. The actual first argument doesn’t really matter, you can even look at the JS file that contains this function call and you will see it isn’t even referenced (htmldb_html_elements.js). The real worker of this function call is the URL. FLOW_PPR_OUTPUT_ triggers an internal APEX function that will trigger the page rendering. The RP identifier forces the pagination to return to page one, which is just a precautionary measure to be safe. Since the reports rows may be removed or added it is nicer to avoid the error message as it will force a full page refresh, just what we were avoiding.

The only other thing that is required is to remember to put the PPR tags in your report template. In the before rows section after the outer most container but before any #PAGINATION# replacements strings or the start of the report:

<HTMLDB:#REGION_ID#>

And this after the report, after any #PAGINATION# tags, but before the outer closing tag:

</HTMLDB:#REGION_ID#>

And this script block at the very bottom:

    init_htmlPPRReport('#REGION_ID#')

The function call, init_htmlPPRReport, enables PPR sorting within the report. There are also function calls that need to be in the pagination template, which are easily obtainable by either copying them from one of APEX’s PPR templates or creating a new PPR template.

What I don’t like about PPR in APEX is that even though you are refreshing a single report, the entire page is generated server side and sent to the client. It is a complete HTML mock up (You can use FireBug in FireFox to inspect the AJAX request if you are curious). It then uses text parsing to find the specific report you are refreshing via the HTMLDB:#REGION_ID# tags and then uses INNER HTML to put the markup in place. Not exactly elegant, but at least the visual effect of AJAX is there.

  • Reddit
  • del.icio.us
  • Google Bookmarks
  • StumbleUpon
  • Technorati
  • Digg

6 Responses to “Refreshing Apex Reports Via PPR”

  1. Leonid Pavlov said:

    Jul 16, 07 at 9:14 am

    Hi,

    very interesting.

    But is it possible to refresh the region from another page?
    I think no, but may be you have any idea?

    For example:
    I have 2 Pages: Page2 is the Page in the IFRAME on the Page1. I want to refresh Page1 from Page2.

    Regards,

    Leonid Pavlov

  2. Carl Backstrom said:

    Jul 16, 07 at 4:32 pm

    One thing to do is to use a simplified page template for your page 2.

    If you look at my old example here.

    It uses a very simplified page template for the second page http://apex.oracle.com/pls/otn/f?p=11933:48 which keeps the AJAX

    Carl

  3. Andrew Martinez said:

    Jul 18, 07 at 1:16 am

    You sure can do it across iframes/windows (iframes are just embedded windows). You have to have the window context of the other page. If page1 has an iframe we will call page2, you can use window references in JavaScript to run code cross iframe. The key words you would be looking to use are either:

    window – the current window
    parent – the window that opened this window
    top – the outer most parent window (incase of multiple embeds)

    From a window context you can run any JavaScript function you wish. I.E to get an element by id of the parent window you can do the following:

    parent.document.getElementById( “P1_ITEM_NAME” );

    Using this principle you could execute a function that works on within the parent page to refresh your region.

    1- in page 2 run the JS: parent.refreshRegion1();
    2 – in page 1, ensure that function refresRegion1(){ … } is defined and refreshes the region you wish.

    Note that executing script cross window/iframe is subject to some strict rules since it is a gateway into Cross-Site Scripting, a hacking technique. By default, scripts can only work across windows/iframes that share the same domain name.

  4. Leonid Pavlov said:

    Jul 20, 07 at 8:22 am

    Hi all,

    thank you for the answers. I have solved it with help of Carl’s solution. There is the solution:
    http://apex.oracle.com/pls/otn/f?p=31269:1

  5. Leonid Pavlov said:

    Jul 20, 07 at 8:23 am

    Username/password: guest/guest

  6. naani said:

    Dec 03, 09 at 6:03 pm

    I follow the above instructions and get below error, please can you point me what I am doing incorrect? thanks
    Bad Request
    Your browser sent a request that this server could not understand.
    mod_plsql: /pls/apex/f HTTP-400 Bad name in the request: not a legal PLSQL identifer


Leave a Reply