APEX Training

Sunday, 14 June 2009

Use Lightbox 2 in Apex

Following this thread I was wondering how easy it is to incorporate the Lightbox 2 plugin into Apex on apex.oracle.com. You can see the results here in my Demo Application.

Tabular Forms - Autofill

Tabular Forms are used to manage master-detail dependencies. Usually for creating applications like:

- Order Management or
- Quote Management

For order or a quote management you would create a simple form to manage your header data. Tabular form would be used for order lines having hidden fileds for primary key and foreign key (order primary key). Order lines are usually items comming from an item master table. Sometimes, these line items are available through a select list and the most of the information you need in a tabular form is already available and could be filled automatically:

- item description
- price
- quantity (default 1)
- other item properties

In this example in my Demo Application you can see how that can be done.

Selecting a product from the list would use Ajax to get the related information from the item master table for the selected product_id.

An on demand process would generate an xml stream and send it back to the page.

<desc>this xml genericly sets multiple items</desc>
<item id="f32_2">JavaScript: The Definitive Guide</item>
<item id="f33_2">31.49</item>
<item id="f34_2">David Flanagan</item>
<item id="f35_2">1</item>

A piece of javascript code would loop through that xml string and assign the values returned to the specified items in the tabular form.

Thursday, 4 June 2009

How to Debug Ajax and On Demand Processes

I am getting several emails every week regarding one the same issue - Ajax and On Demand Process. In the most of the cases there is a problem with the On Demand Process code. Unfortunatelly Apex is not going to compile your code once you save it. If there is an error in your code the results will not be as expected. On the other side it is quite easy to debug that:

1. Try running your code in SQL Workshop - if your process is supposed to generate an XML file for a select list, you should see a select list if the code is O.K.

2. Use Firefox and download Firebug. Using Firebug you will be able to immediatelly see the results of the On Demand Process you created. Just open the Console and run your process:

3. Be carefull with naming of your On Demand Process - the name of your process in the javascript has to exactly match the name of the process in application processes. Using Firefox and Firebug will help to find that out:

4. Javascript is using htmldb_Get function to call your process the same way you would do that by typing it in the browser address bar - having a blank character there would retreive no results. That means that thhe part of the javascript code


equals to


5. This would also mean that you can test your process using a simple link in your browser:

6. Make sure to name your application and page items correctly in the javascript part of the code. If your misstype a name no explicit error message will be issued. However, using Firefox and Firebug you will see a lot of javascript code in the Console and eventually find an error like displayed in the following screenshot:

7. Finaly, opening the "Post" Tab in Firebug, you will get an overview of your main parameters:

Enjoy debugging your ajax code.

Magic Page 0

In this posting I explained how to overwrite css rules using page header text or a conditional region. Something similar is also possible using the page 0. One of my customers asked me to create a page template in a corporate layout which they could use for their future applications. The only difference between the applications would be the image they display in the page header. The customers also had a mix of different browsers starting with IE6 over IE7 and Firefox. There were two problems I was faced with:

1. how to easily apply / change the image displayed in the header of the application

2. different browsers (IE6) would interpret my css code differently than the other browsers

I solved the problem in the following way:

1. created a page 0

2. created a "No Template" Region on the page

3. added the following code to the region source

<style type="text/css">
background-repeat: no-repeat;
background-position: 290px -45px;

background-repeat: no-repeat;
background-position: 290px -15px;}


<!--[if gte IE 6]>
<style type="text/css">

The style part of the code would display the custom image. The javascript part would overwrite the style for the navigationArea if IE6 is used to view the page. Once they create a new application the only thing that needs to be done is to copy the page 0 from one of the existing applications and change the image name.

Tuesday, 2 June 2009

Function Returning Links

In Apex you can create links out of your columns in a report. What you currently can't do is to put a condition behind this link and generate it upon that condition - if there is a link then it is there for all the rows. The only workarround for this is to create the link in your SQL. In that case your SQL may look quite clumsy and hard to read. Something like this:

WHEN deptno = 10
THEN '<a href="javascript:popUp2('''
|| 'f?p=&APP_ID.:500:&SESSION.::&DEBUG.::'
|| 'P500_DEPTNO:'
|| deptno
|| ''', 700, 700);">'
|| '<img src="#IMAGE_PREFIX#gobut.gif">'
|| '</a>'
WHEN deptno = 20
THEN '<a href="javascript:popUp2('''
|| 'f?p=&APP_ID.:501:&SESSION.::&DEBUG.::'
|| 'P501_DEPTNO:'
|| deptno
|| ''', 700, 700);">'
|| '<img src="#IMAGE_PREFIX#go_search.gif">'
|| '</a>'
ELSE '<a href="javascript:popUp2('''
|| 'f?p=&APP_ID.:502:&SESSION.::&DEBUG.::'
|| 'P502_DEPTNO:'
|| deptno
|| ''', 700, 700);">'
|| '<img src='
|| '"#WORKSPACE_IMAGES#go_button.gif">'
|| '</a>'
ename, job, hiredate
FROM emp

The solution for this problem you can find here. Back in 2006 I created a function for generating links. This function can do the following for you:

- create a link based on a target page you provide, withouth having to code a full apex link,
- replace the link with an image if desired,
- sort the links based on any columns in your source,
- open the target page in the same window or in a popup window,
- add a request to your link,
- reset pagination if required,
- add a checksum to your link.

At the end, your query looks much better if you use that function:

WHEN deptno = 10
THEN return_link_fn (p_page => 500,
p_item => 'P500_DEPTNO',
p_value => deptno,
p_image_n => 'gobut.gif'
WHEN deptno = 20
THEN return_link_fn (p_page => 501,
p_item => 'P501_DEPTNO',
p_value => deptno,
p_image_n => 'go_search.gif'
ELSE return_link_fn (p_page => 502,
p_item => 'P502_DEPTNO',
p_value => deptno,
p_image_n => 'go_button.gif'
ename, job, hiredate
FROM emp

Monday, 1 June 2009

Applying CSS Conditionally

It may happen that you have an exception on one or more of your pages where your styling deviates from standard. In addition to that, you may want to apply your style conditionally. You have several choices in order to solve that problem:

1. make changes to your css file
2. create a css file within your workspace and reference it in your page template
3. create an additional template for your new style

However, this reqiures severals steps and could be a problem in some cases:

- you are not managing your HTTP Server and your dba's need months in order to accept such a small change

- you need to make changes to your page templates

- you need to create an additional template (region template, report template, ...)

Sometimes you need to go that way but there are also situations where you could solve that as in this example in my Demo Application. Using Firefox and Web Developer Toolbar you can easily find out the classes and their properties referenced in your template. You can adjust those properties to whatever you need and put that code into the header text of your page:

.t10ReportsRegion .t10RegionBody {background-color:#E2E5EA;}
.t10ReportsRegion .t10ButtonHolder {background-color:#E2E5EA;}

and the style will be applied only on that particular page. This will overwrite the style applied through the class with the same name in your css file.

If you need to apply your style conditionally, you can do the following:

1. create a region with the highest sequence and do not apply any template to it,

2. put your code in the region source of that region

3. change the region to render conditionally