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.

javascript:apex.submit({request:'SAVE',set:{'P5_EMPNO':'#EMPNO#'}});

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.