Building a Ext JS Theme into Oracle APEX

Exclusive offer: get 50% off this eBook here
Oracle Application Express 4.0 with Ext JS

Oracle Application Express 4.0 with Ext JS — Save 50%

Deliver rich desktop-styled Oracle APEX applications using the powerful Ext JS JavaScript library with this book and eBook

$32.99    $16.50
by Mark Lancaster | April 2011 | Enterprise Articles Oracle

This article by Mark Lancaster, author of Oracle Application Express 4.0 with Ext JS, covers building a theme based application on Ext JS into APEX. It provides a background on APEX themes and discusses how to create an APEX theme from scratch. Instructions on how to integrate the Ext JS library into the page template are provided, together with potential issues you may encounter. This article includes:

  • An overview of APEX themes, explaining the template types that make up a theme, as well as the benefits of separating the APEX engine, templates, and application functionality from each other.
  • Starting out creating a APEX Theme.
  • Building a Page Template based on the Ext.Viewport component. This covers the process of creating a template using a standalone prototype and integrating it into an APEX page template.
  • Discussion on how JavaScript DOM manipulation can result in input items appearing outside the form element, and the consequences that result. A customized version of the Ext.Viewport is created to ensure that input items always remain with the form.

 

Oracle Application Express 4.0 with Ext JS

Oracle Application Express 4.0 with Ext JS

Deliver rich desktop-styled Oracle APEX applications using the powerful Ext JS JavaScript library

        Read more about this book      

(For more resources on this subject, see here.)

Theme basics

Out of the box, APEX comes with twenty themes, each theme comprising a collection of templates used to define the layout and appearance of an entire application. An application can have many themes, but only one theme is active at any time; switching themes is done at design time only.

You can create custom themes, which may be published, either within a workspace by a Workspace Manager or for the whole APEX instance by an Internal Workspace Manager. Publishing a theme encourages consistency across applications.

A theme comprises nine template types: breadcrumb, button, calendar, label, list, page, popup list of values, region, and report. A theme must have at least one of each of the nine template types.

Within each template type are a set of predefined classes and eight custom classes. For example, the label template has the following classes:

  • - Not Identified -
  • No Label
  • Optional Label
  • Optional Label with Help
  • Required Label
  • Required Label with Help
  • Custom 1... Custom 8

Programmers use these templates to construct the HTML pages that make up an application. Each page is declaratively defined using metadata to select templates to be used for the presentation.

The APEX engine dynamically renders an HTML page using the metadata, assembling relevant templates and injecting dynamic data into placeholders within the templates. The HTML page is viewed when you request a page through a web browser. When you submit a page, the APEX engine performs page processing, once again using declaratively defined metadata to perform computations, validations, processes, and branching.

This type of processing is a typical Model-View-Controller(MVC) pattern, where the view is the HTML generated using the application templates. The APEX engine is the controller and receives the GET or POST input and decides what to do with it, handing over to domain objects. The domain objects model is encapsulated in the page definition and contains the business rules and functionality to carry out specific tasks.

Separation of concerns

The MVC pattern also promotes another good design principle—separation of concerns. APEX has been designed so that the APEX engine, templates, and the application functionality can be optimized independently of each other.

Clearly, the process of assembling and sequencing the steps necessary to render a page, and process a page are important to the overall solution. By separating this out and letting Oracle deal with the complexities of this through the APEX engine, it allows programmers to concentrate on providing business functionality.

Equally, by separating presentation templates from the business logic, it allows each aspect to be maintained separately. This provides a number of advantages including ease of design change, allowing templates to be modified either by different people or at different times to enhance the interface without breaking the application.

An excellent example of this is the standard themes provided in APEX, which have been designed to be completely interchangeable. Switching standard themes is simply a matter of loading a theme from the repository and then switching the active theme. APEX then remaps components to the new active theme using the template class identifiers.

Standard themes

We will be building our own custom theme rather than using one of the twenty pre-built ones. Nevertheless, it's worthwhile knowing what they provide, as we will build our custom theme by using one of them as a "starter".

Building a Ext JS Theme into Oracle APEX

Looking at this image, we can see a preview of the standard APEX themes. Each theme provides a similar interface, so really each standard theme is just a visual variation on the others. The colors used are a little different, or the HTML layout is tweaked slightly, but in reality they are all much the same.

Theme 4 is used by APEX as the "starter" theme and contains one template for each template class for all the template types—a total of 69 templates. Theme 19 is also worth noting as it's designed for mobile devices. Each of these themes are full of good HTML practices and show how and where to use the substitution strings.

Creating a theme

When creating a theme, you can choose to copy one from the repository, create one from scratch or from an export file. The repository and export file options copy the entire theme, and you start editing the template to suit. Creating a theme from scratch creates a theme without any templates. You then need to define templates for each different type before you can switch from the active theme.

In my opinion, the easiest way to build a new theme is to take the approach that the application should always be in a working state, and the way to do this is to create a new empty TEMPLATE application using a standard theme and build from there.

From this working base, you can progressively convert the templates to use Ext functionality, building simple test pages as you go to verify the templates. These test pages also form part of your template documentation, allowing team members to examine and understand specific functionality in isolation.

Once a theme has templates for each of the nine template types, you can publish the theme into the workspace to be used by your business applications.

The following screenshot shows a dialog named Create Workspace Theme from the APEX wizard. Notice that you can change the theme number when you publish a theme, providing a very simple mechanism for you to version control your themes.

Building a Ext JS Theme into Oracle APEX

A published theme can't be edited directly once it has been created, but using a TEMPLATE application, you can republish it using a different theme number. Applications can have multiple themes, but only one active theme. By switching themes, applications can easily test a new version, safe in the knowledge that changing back to the earlier version is just a matter of switching back to the prior theme.

So before we go any further, create a new TEMPLATE application based on Theme 4, and let's begin the process of creating our Ext JS theme.

Building a Viewport Page template

Several of the examples provided with Ext feature the Viewport utility container, including the RSS Feed Viewer shown in the screenshot below. The Viewport automatically renders to the document body, sizing itself to the browser viewport and dividing the page into up to five distinct regions; the center region is mandatory, with north, south, east, and west regions being optional.

Building a Ext JS Theme into Oracle APEX

Viewport regions are configurable, and by setting a few simple attributes, you quickly find yourself with a very interactive page, with expanding/collapsing regions and splitters to resize regions by clicking and dragging with the mouse.

We are going to build a basic viewport for our APEX page template including all five regions.

Oracle Application Express 4.0 with Ext JS Deliver rich desktop-styled Oracle APEX applications using the powerful Ext JS JavaScript library with this book and eBook
Published: March 2011
eBook Price: $32.99
Book Price: $54.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on this subject, see here.)

Starting with a standalone template

Once again we're going to take a prototyping approach to building an APEX page template. It's easier to build a standalone HTML page and make sure we've got the JavaScript right, and then load it into APEX.

<html>
<head>
<title>#TITLE#</title>
<link rel="icon" href="#IMAGE_PREFIX#favicon.ico"
type="image/x-icon">
<link rel="shortcut icon"
href="#IMAGE_PREFIX#favicon.ico"
type="image/x-icon">

<!-- css includes -->
<link rel="stylesheet" type="text/css"
href="../../extjs/resources/css/ext-all.css">
<link rel="stylesheet" type="text/css"
href="ex3-1-local-viewport.css">

<!-- js includes -->
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../../extjs/adapter/ext/ext-base.js">
</script>
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../../extjs/ext-all.js">
</script>
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="ex3-1-local-viewport.js">
</script>
</head>
<body>
<div id="app-north-panel">
<div id="app-logo"><a href="&HOME_LINK.">#LOGO#</a>
</div>
<div id="app-navigation-bar">
#NAVIGATION_BAR# #CUSTOMIZE# &APP_USER.
</div>
#REGION_POSITION_01#
</div>
<div id="app-west-panel">#REGION_POSITION_02#</div>
<div id="app-center-panel">
#FORM_OPEN#
<div id="app-messages"> #GLOBAL_NOTIFICATION##SUCCESS_
MESSAGE##NOTIFICATION_MESSAGE#
</div>
<div id="app-content">#BOX_BODY#</div>
#FORM_CLOSE#
</div>
<div id="app-east-panel">#REGION_POSITION_03#</div>
<div id="app-south-panel">footer contents go here</div>
</body>
</html>

The code shows the content of the standalone HTML page located in ex3-1-local-viewport.html (code download-Ch:3), which contains a mixture of HTML elements and APEX substitution tags (key words are enclosed by # characters).

Looking at the header section enclosed by HEAD tags, you can see the standard Ext components: stylesheet ext-all.css, adapter layer ext-base.js, and library extall.js are present. Also included are our application CSS and JavaScript files: ex3-1-local-viewport.css and ex3-1-local-viewport.js.

The body section, enclosed by BODY markup tags, contains a series of DIV tags with region IDs, for example, app-north-panel, which will become panels in our viewport. APEX uses #FORM_OPEN# and #FORM_CLOSE# substitution tags to define the HTML form element wwvFlowForm used for all APEX pages.

In this template, region tags #REGION_POSITION_01#, #REGION_POSITION_02#, and #REGION_POSITION_03# are outside of the #FORM_OPEN# and #FORM_CLOSE# substitution tags, so they cannot be used for APEX input items, which we will cover in more depth shortly in the Issue when input items are outside the form section.

The accompanying JavaScript located in ex3-1-local-viewport.js is:

Ext.onReady(function(){
Ext.BLANK_IMAGE_URL = '../../extjs/resources/images/
default/s.gif';

new Ext.Viewport({
layout: 'border',
defaults: {
animCollapse: false,
autoScroll: true
},
items: [{
applyTo: 'app-north-panel',
autoHeight: true,
autoScroll: false,
region: 'north',
style: {padding: '0 5px'},
xtype: 'box'
}, {
contentEl: 'app-south-panel',
height: 30,
region: 'south',
style: {padding: '0 5px'},
xtype: 'box'
}, {
contentEl: 'app-west-panel',
//collapseMode: 'mini',
collapsible: true,
margins: '0 0 0 5',
maxSize: 500,
minSize: 100,
region: 'west',
split: true,
title: 'Navigation',
width: 275
}, {
contentEl: 'app-center-panel',
region: 'center',
title: document.title,
xtype: 'panel'
}, {
contentEl: 'app-east-panel',
collapseMode: 'mini',
collapsible: true,
margins: '0 5 0 0',
maxSize: 500,
minSize: 100,
region: 'east',
split: true,
title: 'Actions',
width: 275
}]
});
});

The JavaScript could be summarized as follows:

Ext.onReady(function(){
Ext.BLANK_IMAGE_URL = '../../extjs/resources/images/
default/s.gif';
new Ext.Viewport({ configuration });
});

Looking at the summarized version, we are passing an anonymous function to Ext.onReady, which executes the function after waiting for only the document structure to be fully parsed and the HTML converted into a DOM tree. This performs better than the traditional window.onload handler, which waits for the entire page to be fully loaded before executing.

The anonymous function contains two statements; the first assigns the location image of the 1x1 pixel transparent spacer image using the following code:

Ext.BLANK_IMAGE_URL = '../../extjs/resources/images/default/s.gif';

The second statement instantiates a new Ext.Viewport object passing its configuration settings as a config object:

new Ext.Viewport({ ..configuration.. });

Ext.Viewport is a specialized container that renders to the document body, automatically resizing when the browser window is resized. Viewports contain up to five pre-defined regions (or panels) defined in the items object, with the center region being mandatory. Each of these panels is separately configured, and can inherit default configurations from the viewport.

new Ext.Viewport({
layout: 'border',
defaults: {
animCollapse: false,
autoScroll: true
},
items: [{
applyTo: 'app-north-panel',
autoHeight: true,
autoScroll: false,
region: 'north',
style: {padding: '0 5px'},
xtype: 'box'
}, {
contentEl: 'app-south-panel',
autoScroll: false,
height: 30,
region: 'south',
style: {padding: '0 5px'},
xtype: 'box'
},

Looking at the first part of the Viewport configuration, you can see that defaults are set for animCollapse to switch off animation for collapsing regions, and autoScroll set to true, enabling scrollbars to appear in regions. These defaults are applied to all of the regions defined within items, unless specifically overridden, as shown in the north region.

When using north or south regions, you must specify a height; similarly for east and west regions, you must specify a width. For the south region here, I've set the height property in pixels, and for the north region I've used set autoHeight: true to show an alternative method.

Notice that the north region is using applyTo: 'app-north-panel', whereas the south region is using contentEl: 'app-south-panel'. The attributes produce a subtly different outcome when rendered; one takes an existing HTML element and places it into the layout of the viewport, where the other uses the existing DOM element as part of the layout. Can you work out which attribute does what? Consult the Ext documentation and inspect the HTML using Firebug and verify.

In this example, the difference between using applyTo and contentEl doesn't adversely impact the behavior, but it's a little reminder to take a little extra time to understand what's happening.

In the west region is a commented-out line //collapseMode: 'mini'. Try collapsing and expanding the panel before comparing the behavior to the east region. When in mini mode the regions split bar displays a small collapse button appears in the center of the bar, and the region collapses to a thinner bar than in normal mode. Which collapseMode do you prefer?

Finally, the CSS file ex3-1-local-viewport.css contains the following CSS:

#app-navigation-bar {
color:grey;
position:absolute;
right:5px;
}

There is almost nothing in our CSS file; just one rule to right align the app-navigation-bar DIV element in our template. With so little content in our CSS file, it's hardly worth having a separate file; we could instead just include it within the page.

Remember here that we're taking the first step in building our application CSS, and we are going to be adding more rules as we go. So let's start a good habit and include the CSS that is going to be used by every page request using the template in a separate file, taking advantage of static file caching by the browser and reducing the size of our dynamically generated page.

Building a Ext JS Theme into Oracle APEX

This screenshot shows what our prototype looks like in the browser window.

The north region on the left-hand side contains APEX substitution tags #LOGO# for the application logo, and #REGION_POSITION_01# for breadcrumbs. The right-hand side contains substitution tags for #NAVIGATION_BAR#, #CUSTOMIZE#, and &APP_USER.

The west region is titled Navigation, and contains the #REGION_POSITION_02# substitution tag. As the name suggests, you would include links in this panel to navigate your application. Similarly, the east region contains the #REGION_POSITION_03# substitution tag, and could be used for actions specific to the page.

The center region's title is dynamically assigned in our viewport definition to use JavaScript document.title property, which in our page is the #TITLE# substitution tag. The center region body contains the #FORM_OPEN# and #FORM_CLOSE# tags that enclose the notification and message substitution tags #GLOBAL_NOTIFICATION#, #SUCCESS_MESSAGE#, #NOTIFICATION_MESSAGE#, along with the #BOX_BODY# substitution tag for our page content.

The south region here contains some plain text, and would typically be used for page referencing and copyright information.

Loading the page template into APEX

So all that remains is to transfer the prototype into APEX as a page template, and then make a couple of minor adjustments.

Currently the path to our included JavaScript and CSS files is:

<!-- css includes -->
<link rel="stylesheet" type="text/css"
href="../../extjs/resources/css/ext-all.css">
<link rel="stylesheet" type="text/css"
href="ex3-1-local-viewport.css">
<!-- js includes -->
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../../extjs/adapter/ext/ext-base.js">
</script>
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../../extjs/ext-all.js">
</script>
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="ex3-1-local-viewport.js">
</script>

You will need to modify the path for the src attributes to suit the location of the files on your web server.

If you are using a hosted APEX environment, such as apex.oracle.com, you can reference Ext JS files using the CacheFly content delivery network, for example, for ext-all.js, use http://extjs.cachefly.net/ext-3.3.1/ext-all.js.

The #HEAD# substitution tag needs to be added in the HTML header to include the standard APEX JavaScript in the page template. APEX will automatically add JavaScript and CSS includes replacing the substitution tag. It is best to add the tag before our JavaScript and CSS files, as it allows our custom code to override both CSS rules and JavaScript functions when needed.

For this article the Ext library is stored on the web server under /ux/extjs/, and application assets under /ux/playpen/, so the path looks like:

#HEAD#

<!-- css includes -->
<link rel="stylesheet" type="text/css"
href="/ux/extjs/resources/css/ext-all.css">
<link rel="stylesheet" type="text/css"
href="/ux/playpen/ex3-1-local-viewport.css">

<!-- js includes -->
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="/ux/extjs/adapter/ext/ext-base.js">
</script>
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="/ux/extjs/ext-all.js">
</script>
<script type="text/javascript"
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="/ux/playpen/ex3-1-local-viewport.js">
</script>

The other change you will need to make is to change the ex3-1-local-viewport.js file modifying the location of the 1x1 pixel transparent spacer image to: Ext Ext.BLANK_IMAGE_URL = '/i/1px_trans.gif';.

Here, we are referencing a blank image that is part of the standard APEX install.

Now, open one of the existing page templates. This example uses the No Tabs with Sidebar template. Replace content of the header, body, and footer regions with the updated content from the prototype, as shown in the following screenshot:

Building a Ext JS Theme into Oracle APEX

Rename the template to EXTJS No Tabs with Sidebar, so it's easy to recognize the updated template and apply the changes.

Finally, copy the ex3-1-local-viewport.js and ex3-1-local-viewport.js files onto your web server in the location referenced in the page template.

Create a blank page using the newly created template, and run the page. It should look the next screenshot:

Building a Ext JS Theme into Oracle APEX

Looking at the North panel, we haven't specified a logo in the Application properties so the #LOGO# substitution tag has been replaced with an empty value. The layout issues on the right-hand side with the navigation bar and user name are caused by additional HTML included in the Subtemplate section of the page template. The appearance of the links in the header needs further refinement, which we will do a little later under breadcrumb templates. So, although we have made a good start on the page template, there is still more to do.

To fix the navigation bar on the right-hand side so that the user name is on the same line, update the page template, changing the Subtemplate as follows.

Building a Ext JS Theme into Oracle APEX

While we are working on the Subtemplate, we might as well modify the Success Message and the Notification entries also.

Building a Ext JS Theme into Oracle APEX

The Success Message, shown at the top of the preceding screenshot, uses the following HTML:

<div id="app-notification" class="app-success">
<div class="x-tool x-tool-close"
onclick="Ext.fly('app-notification').remove();"
style="display: block; margin-left:5px">&nbsp;</div>
<div>#SUCCESS_MESSAGE#</div>
</div>

And it requires the following CSS rule to be included in the CSS file:

.app-success {
background:none repeat scroll 0 0 #DFE8F6;
border:1px dotted #99BBE8;
color:#15428B;
cursor:default;
clear: both;
font:normal 11px tahoma,arial,sans-serif;
padding:5px 0;
text-align:center;
margin:10px 30%; width:40%;
}

Functionally, it is the same as the standard APEX content it replaces; a DIV region displaying a message, with an image that deletes the region when clicked. JavaScript purists may complain about including JavaScript code in the highlighted onclick attribute.

The "better" way would be to remove the onclick attribute and adding the following code to add a listener in your application JavaScript:

Ext.onReady(function(){
/*… application code before…*/
if (Ext.fly('app-notification')) {
Ext.fly('app-notification').on('click', function(){
this.remove();
});
}
});

Both ways achieve the desired outcome; it's just a matter of personal preference which way you want to code.

The Notification entry in the previous screenshot is a more complicated layout based on the HTML created by Ext.Alert, allowing the reuse of existing Ext CSS rules. It provides similar functionality to the Success Message; the HTML source is in ex3-2-local-viewport.html (code download-Ch:3).

The page template now has all the page definition and also the Subtemplate sections completed. But that's not the end of the page template just yet! There is a nasty issue potentially lurking in the template, where input items can appear outside the FORM element, which needs to be addressed.

Oracle Application Express 4.0 with Ext JS Deliver rich desktop-styled Oracle APEX applications using the powerful Ext JS JavaScript library with this book and eBook
Published: March 2011
eBook Price: $32.99
Book Price: $54.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on this subject, see here.)

Issue when input items are outside the form

As web developers, we are becoming more reliant on using JavaScript to manipulate the page layout to provide functionality such as tab panels, accordion regions, popup dialogs, and the like. This leads to existing elements in the DOM being relocated to new positions, and form INPUT items can end up outside the FORM element.

Irrespective of what JavaScript library you use, DOM manipulation can lead to form INPUT items appearing outside the FORM element. In fact, you don't even need to use JavaScript at all to cause the issue, as we will show in this example.

Building a Ext JS Theme into Oracle APEX

This screenshot shows the Page Definition within APEX Builder for a simple page containing the following items of interest:

  • The Contact Details region to be rendered in location Body (3) [#BOX_BODY#], with input items P30_FIRST_NAME, P30_LAST_NAME, and P30_ADDRESS.
  • The Region outside FORM region to be rendered in location Position 2 [#REGION_POSITION_02#], containing item P30_PHONE.

If you refer to the earlier page template, it shows the #REGION_POSITION_02# clearly outside the #FORM_OPEN# and #FORM_CLOSE# substitution tags.

When the page is rendered, and after the layout has been changed using JavaScript, a simplified view of the HTML looks like this:

<html>
<body>
<input type="text" name="p_t01" value="" id="P30_PHONE"/>

<form action="wwv_flow.accept" method="post" name="wwv_flow"
id="wwvFlowForm">
<input type="text" name="p_t02" value="" id="P30_FIRST_NAME"/>
<input type="text" name="p_t03" value="" id="P30_LAST_NAME"/>
<textarea name="p_t04" id="P30_ADDRESS"></textarea>
</form>
</body>
</html>

This shows the highlighted input item, where ID P30_PHONE is clearly outside the FORM tags.

From the HTML code shown, you can see the action for the form is wwv_flow.accept and the item names are p_t01 .. p_t04, corresponding to the database package procedure and parameters being executed by the mod_plsql HTTP request.

When the form is submitted, the values for the inputs are loaded into session state, page processing occurs, and the APEX engine branches to a page. In this example, there is no processing, simply branching to the same page, so the page is rendered again with the passed values.

So, given the P30_PHONE item is not in the form it shouldn't be processed, but what about the items within the form? The following is the result of submitting the form, showing submitted and returned values:

Building a Ext JS Theme into Oracle APEX

So as expected, no value is returned for P30_PHONE, because it was outside the form. However, there is an unexpected displacement of the values, shifting them down, so the P30_FIRST_NAME submitted value of bbb is returned in P30_LAST_NAME, and similarly the value for P30_LAST_NAME is returned in P30_ADDRESS. The whereabouts of the value for P30_ADDRESS is unknown and is not easily explained.

Without having access to the source code for the APEX engine, it is only possible to speculate on why this occurs. Nevertheless, we still need to deal with the issue and come up with a strategy to prevent it from occurring.

Ensuring input items always remain with the form

To ensure form items always remain within the FORM element, we need to address both the static HTML issue and potential JavaScript DOM manipulation.

Modify the page template so that all region substitution tags are contained within the #FORM_OPEN# and #FORM_CLOSE# substitution tags, as shown in the following screenshot:

Building a Ext JS Theme into Oracle APEX

The previous screenshot shows the updated Viewport template, addressing the static HTML side of the issue. The #FORM_OPEN# tag now appears immediately after the <body> markup, and the #FORM_CLOSE# tag immediately before the </body> markup.

The only other change is that the application JavaScript file is now ex3-1-custom-viewport.js, which addresses the JavaScript DOM manipulation.

To ensure form items always remain within the form element, we can use a customized version of Ext.Viewport, which uses the APEX form element wwvFlowForm as the container for the viewport, instead of the body element.

// create custom namespace if doesn't exist
Ext.ns('Ext.apex');

// custom container
Ext.apex.Viewport = Ext.extend(Ext.Container, {
initComponent : function() {
Ext.apex.Viewport.superclass.initComponent.call(this);

// APEX specific code
this.el = Ext.get('wwvFlowForm');
if(this.el){
this.el.addClass('x-viewport');
var debug = Ext.getDom('pdebug');
if (!(debug && (debug.value == 'YES'))) {
document.getElementsByTagName('html')[0].className += '
x-viewport';
}
} else {
this.el = Ext.getBody();
document.getElementsByTagName('html')[0].className += '
x-viewport';
}

this.el.setHeight = Ext.emptyFn;
this.el.setWidth = Ext.emptyFn;
this.el.setSize = Ext.emptyFn;
this.el.dom.scroll = 'no';
this.allowDomMove = false;
this.autoWidth = true;
this.autoHeight = true;
Ext.EventManager.onWindowResize(this.fireResize, this);
this.renderTo = this.el;
},
fireResize : function(w, h){
this.fireEvent('resize', this, w, h, w, h);
}
});

// Register container so that lazy instantiation may be used
Ext.reg('apex-viewport', Ext.apex.Viewport);

The script starts by creating a custom namespace, Ext.apex, to ensure that we don't pollute the global namespace. The Ext.apex.Viewport is then defined, which is a direct copy of the Ext.Viewport, excepting the highlighted APEX specific code.

For APEX, the code checks to see if the APEX form element with the wwvFlowForm ID is present in the page, and if yes, whether it uses this as containing item for the Viewport. When wwvFlowForm is not present, it reverts to standard Ext.Viewport functionality, using the document body instead. This is useful when previewing the page template, or selecting the location for a region in the APEX Builder.

Finally, the container is registered so that lazy instantiation can be used using the xtype attribute value of apex-viewport. See the panel definitions in the application code for examples of xtypes box and panel.

A check is also done to see if APEX is in debug mode, and if yes, it ensures the HTML page allows scrolling, otherwise scrolling is disabled for the page and scrolling is managed within the viewport using Ext features.

To use the custom viewport, we simply replace calls to Ext.Viewport with Ext.apex.Viewport like this:

Ext.onReady(function(){
Ext.BLANK_IMAGE_URL = '../../extjs/resources/images/
default/s.gif';

new Ext.apex.Viewport({ configuration });
});

The custom viewport needs to appear before the application code in the JavaScript file. The application code has also been modified to show the east panel only when its container app-east-panel has child nodes other than text.

Ext.onReady(function(){
var items = [];

Ext.BLANK_IMAGE_URL = '/i/1px_trans.gif';

items.push({
applyTo: 'app-north-panel',
autoHeight: true,
autoScroll: false,
region: 'north',
style: {padding: '0 5px'},
xtype: 'box'
}, {
contentEl: 'app-south-panel',
autoScroll: false,
height: 30,
region: 'south',
style: {padding: '0 5px'},
xtype: 'box'
}, {
contentEl: 'app-west-panel',
//collapseMode: 'mini',
collapsible: true,
margins: '0 0 0 5',
maxSize: 500,
minSize: 100,
region: 'west',
split: true,
title: 'Navigation',
width: 275
}, {
contentEl: 'app-center-panel',
region: 'center',
title: document.title,
xtype: 'panel'
});

// conditionally add east panel if it contains
child nodes
if (Ext.fly('app-east-panel') &&
Ext.fly('app-east-panel').first()) {
items.push({
contentEl: 'app-east-panel',
collapseMode: 'mini',
collapsible: true,
margins: '0 5 0 0',
maxSize: 500,
minSize: 100,
region: 'east',
split: true,
title: 'Actions',
width: 275
});
}
new Ext.apex.Viewport({
layout: 'border',
defaults: {
animCollapse: false,
autoScroll: true
},
items: items
});
});

The page template is now complete and the issue of input items appearing outside the form element has been resolved.

Summary

We have seen how APEX page processing fits a typical Model-View-Controller (MVC) pattern, where the view is the HTML generated using the application templates. The APEX engine is the controller and receives the GET or POST input and decides what to do with it, handing it over to domain objects. The domain objects model is encapsulated in the page definition and contains the business rules and functionality to carry out specific tasks.

This separation of concerns provided by the MVC pattern allows APEX to easily swap themes for an application. The publishing mechanism allows new versions of a theme to be built separately from the application. By switching themes, applications can easily test a new version, safe in the knowledge that we can revert to the earlier version if required.

We then set about creating a page template, using a standalone prototype initially to make sure the markup and JavaScript works correctly before loading it into APEX. Once a few adjustments were made to load it, the page template was up and running in APEX. This revealed some layout issues with the navigation sub-template (which was corrected), as along with the success and error notifications.


Further resources on this subject:


About the Author :


Mark Lancaster

Mark has been delivering business solutions using Oracle tools and technology since 1995. He switched to using Oracle APEX in 2007 after using mod_plsql for years - "APEX is much much better". He has had the good fortune of consulting for a wide variety of organizations in industries including commercial fishery management, mineral resources, superannuation regulation, property asset management, distance education, casinos and debt collection. Mark is an Oracle ACE, having been actively involved in the Oracle community for many years on national and state committees, as well as writing articles and presenting at conferences.

He is the AUSOUG QLD Branch President, and maintains a blog at http://oracleinsights.blogspot.com.

Books From Packt


Oracle APEX 4.0 Cookbook
Oracle APEX 4.0 Cookbook

Learning Ext JS 3.2
Learning Ext JS 3.2

Squid Proxy Server 3.1: Beginner's Guide
Squid Proxy Server 3.1: Beginner's Guide

Oracle Application Express 3.2 - The Essentials and More
Oracle Application Express 3.2 - The Essentials and More

Web 2.0 Solutions with Oracle WebCenter 11g
Web 2.0 Solutions with Oracle WebCenter 11g

Oracle Data Integrator 11g: Getting Started
Oracle Data Integrator 11g: Getting Started

Ext JS 3.0 Cookbook
Ext JS 3.0 Cookbook

Microsoft Azure: Enterprise Application Development
Microsoft Azure: Enterprise Application Development


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software