Sunday, April 22, 2012

Saving Master Before Viewing Detail

The Issue

Master Detail forms are an excellent way to manage a one to many relationship between tables. When using the declarative master detail form, clicking the edit link for a detail record does not save any changes that have been made to the master record. That is because clicking the edit link does not submit the page. A slight modification to the edit link can easily provide that feature. This is also useful for anytime you want to save data and then navigate to another page based on an ID.

This idea is not unique to me, in fact it is completely inspired by the changes made to the APEX builder. When on the Report Attributes tab any changes made to the report definition will be saved when clicking the edit link for a column.

Clicking a Link <> Submit

Before I go any further I want to point out one thing that I think a lot of newer APEX developers have trouble with. Session state for items on a form will not be updated unless the form is submitted. Entering data in a field and then clicking a link to another part of the application is the exact same as entering data and then clicking a link that takes you to another website. There is no instruction for APEX to save the values of the form items.

The Solution

To get started I created a master detail form based on the all too familiar dept and emp tables. Dept being the master and emp being the detail. For this example I had to choose to edit details on a separate page rather than in a tabular form.

Create Detail ID Item
Instead of linking to the detail page we are going to set the value of an item with the ID of the detail record and then submit the page. For this example my item is called P5_EMPNO. Set the source to always replacing, the source type to static, and leave the source value blank. This will ensure that this item is always nulled out to prevent unwanted branching.

Create a Page Branch to the Detail Page
The page branch will redirect to the detail page conditionally if the value P5_EMPNO is not null. Additionally it will set the detail page key(P6_EMPNO) to P5_EMPNO.

Edit the Detail Link to Set the Detail ID and Submit the Page
Rather than link directly to the detail page the detail link is going to save the primary key for the employee into P5_EMPNO and then submit the page with a SAVE request. Change the link target to URL and add the call to apex.submit. This will cause the master record information to be updated and then branch to the detail page. In my case the edit link now looks like this.


Now any changes to the master record will be updated in addition to linking to the detail page. Take a look at the live demo to see how it all pieces together and check back later because I will be rolling out another post which will cover the other features of apex.submit.

Monday, February 27, 2012

SkillBuilders Session Timeout Plugin

It's about time!

I have had this plugin sitting around half-finished for far too long, and with the help of Dan McGhan it is now ready to be released into the wild.

Why Create a Session Timeout Plugin?

Some of you may be asking "Why would someone create a plugin when there is already built in functionality for detecting idle sessions?" Well, the problem arises when the user becomes idle and is unaware that their session is no longer valid. There is a common use case where the user's session becomes idle, but the user is not informed. When the user attempts to interact with the page, AJAX interactions do not work correctly, and when the user finally submits the page they are redirected to login page. That scenario is OK, but I think we can all agree it would be nice to make the user aware of the current status of their session. Before plugins existed, Martin D'Souza created a nice solution to this problem, but it requires some setup. Now that plugins exist the setup can be bundled into one easy to install package.

What does Session Timeout do?

SkillBuilders Session Timeout is a dynamic action plugin that attempts to bridge the gap between server and client when it comes to handling idle sessions. To define session idle length and where to send idle sessions, the plugin uses the properties defined in the security section of the application (If these attributes are not specified the plugin defaults to 30 minute idle time and the redirect URL is the home page).

When an idle session is encountered the plugin can perform one of these Timeout Actions:
  • Alert (default) - An alert message is displayed to lock the screen and inform the user.
  • Redirect - The user is redirected using the On session idle time timeout direct to this URL found in the security section of the application properties. If no value is specified then the user will be redirected to the home page for the application.
  • Logout - Redirects the user to the Logout URL defined in the applications authentication scheme.  If no Logout URL is defined then the following value will be used: apex_authentication.logout?p_app_id=&APP_ID.&p_session_id=&SESSION.
Other options:
  • Keep Session Alive - While the user remains active the server session will be refreshed with an AJAX call.
  • Session Idle Warning - This is a message that will be displayed before the session becomes idle.
  • Mask Browser Screen on Timeout -  This is an extension for the alert action and will create an overlay which hides the contents of the current page when the alert is created.
Installation Instructions

For installation instructions take a look at the Plugin Documentation.
To download the plugin visit the SkillBuilders plugin page.
Visit the demo application to see the plugin in action.

Saturday, January 14, 2012

Printing Main Content Only

The Issue

I was recently asked if it was possible to only print the main content of a page. Occasionally users will print an APEX page by choosing File >> Print in their browser, and the resulting printed output can be a bit messy or contain information they do not care to see. In many cases this is a report the user has filtered and wants to bring to a meeting. Necessary layout components, like a header or sidebar, consume page real estate without providing important information to the printed document. This wasted space can push the content so that the report the user wants to see now prints on multiple sheets of paper.

So the question is, can we print only the main content of a page?

The Solution

Printing the main content of a page can be achieved by using CSS Media Types to style the page differently when it is rendered for a browser than when it is rendered for printing. The solution I opted for was to hide every element on the page except for the element with id="print-content". The idea was originally posted on stack overflow, but I have also included a few helper classes for "print-only" and "no-print" content from within the print-content element. In other words, you may have two regions in the print-content element but you only want one of them to print; the one you do not want to print would be given class="no-print".

Modify the Page Template

Include the following style within the head section of your template. Notice the use of @media print. The enclosed styles will only be applied when the page is being printed.

<style type="text/css"> .print-only{ display: none; } @media print { body * { visibility:hidden; } #print-content, #print-content * { visibility:visible; } #print-content { position:absolute; left:0; top:0; } .print-only { display: block; } .no-print { display:none; } } </style>
Specify Print Content

In this example I am using theme 21 - Scarlet and I am using the One Level Tabs - Left Sidebar (fixed-width / DIV based) page template. I only wanted to print the BOX_BODY and REGION_POSITION_03, so I wrapped that part of my template with a print-content div.

<div id="header"> <div id="logo"> <a href="#HOME_LINK#">#LOGO##REGION_POSITION_06#</a> </div> #REGION_POSITION_07# <div id="navbar"> <div class="app-user">#WELCOME_USER#</div> #NAVIGATION_BAR# #REGION_POSITION_08# </div> </div> <ul id="tabs"> #TAB_CELLS# <li class="last"><span></span></li> </ul> <div id="topbar">#REGION_POSITION_01##REGION_POSITION_04#</div> <div id="messages"> #SUCCESS_MESSAGE##NOTIFICATION_MESSAGE##GLOBAL_NOTIFICATION# </div> <div id="body"> <div id="two-col-sb-left"> <div id="left-sidebar">#REGION_POSITION_02#</div> <div id="main-sb-left"> <div id="print-content"> #BOX_BODY##REGION_POSITION_03# </div> </div> </div> </div>
Have a look at my demo app and try printing the page. The header and sidebar of the page will not show up in the printed document.

Tuesday, December 20, 2011

Refresh-able Charts

The Issue

APEX has come a very long way in helping to declaratively tackle JavaScript interactions with page components. One feature that has saved me countless hours of work is the AJAX refresh-able reports. This feature is leveraged by triggering a "refresh" event that APEX has bound to a report region, and the result is an updated report that reflects the current values of the page items. This behavior is used in almost every application I have created and is also desirable for other region types such as flash charts. Unfortunately, in 4.1, flash chart regions cannot be refreshed in the same way out of the box, but it is possible.

What can be done to make refreshing a chart as simple as refreshing a report?

For those of you who are not familiar with how to refresh a report with a dynamic action have a look at the APEX 4.0 new features application

The Solution

In order to make flash charts refresh-able you will have to perform the following actions:
  1. Modify the chart region template.
  2. Trigger the "Refresh" with a dynamic action.
It should be noted that this only works for flash charts and applications that do not require localization.

1. Modify the Chart Region Template

Add the following snippet of code to the bottom of the chart region template. Then, optionally add a "refreshable-chart" class to the main chart div. This allows you to select all charts on a page with a simple selector. Change the third parameter of apex_RefreshFlashChart to be whichever language you are supporting. Since my application only needs to support English, 'en' works just fine.

<script type="text/javascript"> $('##REGION_STATIC_ID#').bind('apexrefresh',function(){ var region_id = '#REGION_ID#'; $(this).trigger('apexbeforerefresh'); try{ apex_RefreshFlashChart(&APP_PAGE_ID., region_id.substr(1), 'en'); }catch(e){} $(this).trigger('apexafterrefresh'); }); </script>

2. Create the Dynamic Action

Name: refresh_chart
Event: Change
Type: Item(s)
Item(s): P2_DEPTNO

Create two true actions. One to update the session state of your page items and another to refresh the chart. Make sure to include all page items used in your chart region in the Page Items to Submit attribute.

Sequence: 10
Action: Execute PL/SQL Code
PL/SQL Code: null;
Page Items to Submit: P2_DEPTNO

Sequence: 20
Action: Refresh
Selection Type: Region
Region: <your chart region>

The result is a chart that can be refreshed declaratively. One modification to this example could be to change the second true action selection type to jQuery Selector and using the selector .refreshable-chart. This will cause all charts on the page to refresh and could be useful for dashboard type interfaces.

Have a look at my demo application to see how it looks in action.

Obligatory "Taking the Plunge" Post

Who is Tyson Jouglet?

I am a relatively young techie who went to school wanting to become a Java developer. Despite spending numerous hours learning about Java and Object Oriented Programming methodologies my very first job in the programming world was working with Oracle Application Express (APEX) for a company in San Diego CA.  I spent a lot of my time converting Oracle Forms into APEX, becoming familiar with web application development and discovering what the Oracle Database can do. Little did I know what I got myself into...

I now work as a consultant in Huntsville AL developing APEX applications and find myself thoroughly enjoying what I do. When I am not working I am most likely spending time with my now 20-week-pregnant wife.

What to Expect

I primarily created this blog to discuss Oracle APEX and some of the techniques I have used to solve the challenges I have encountered at my daily job. Since web applications involve more than just simple HTML, you can expect to see posts related to some of the following technologies:

  • Oracle APEX
  • PL/SQL and Oracle Database development
  • JavaScript / jQuery
  • HTML / CSS
  • BI Publisher
  • XML / XSL-FO
Given the nature of the ever-expanding tool belt of developers, I am sure this list will continue to grow.

Most Importantly

I want to help you learn something new!