Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

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

£20.99    £10.50
by Mark Lancaster | March 2011 | Enterprise Articles Oracle

This article by Mark Lancaster, author of Oracle Application Express 4.0 with Ext JS, introduces Plug-ins and Dynamic Actions, two of the most exciting new features in APEX 4.0 for developers. For the first time, you have the ability to add custom "widgets" easily and directly into APEX that can be used declaratively in the same way as native APEX components. Plug-ins and Dynamic Actions are supported with back-end integration, allowing developers to make use of APEX provided PL/SQL APIs to simplify component development.

 

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.)

Introduction

Plug-ins and dynamic actions are the two most exciting new features for developers in APEX 4.0. Combining them with Ext JS components is a recipe for success.

For the first time we now have the ability to add custom "widgets" directly into APEX that can be used declaratively in the same way as native APEX components. Plug-ins and dynamic actions are supported with back end integration, allowing developers to make use of APEX provided PL/SQL APIs to simplify component development.

Plug-ins give developers a supported mechanism to enhance the existing built-in functionality by writing custom PL/SQL components for item types, regions, and processes.

Dynamic actions provide developers with a way to define client-side behavior declaratively without needing to know JavaScript. Using a simple wizard, developers can select a page item and a condition, enter a value, and select an action (for example, Show, Hide, Enable, and Show Item Row).

Most APEX developers come from a database development background. So, they are much more comfortable coding with PL/SQL than JavaScript. The sooner work is focused on PL/SQL development the more productive APEX developers become.

The ability to create plug-ins that can be used declaratively means developers don't have to write page-specific JavaScript for items on a page, or use messy "hacks" to attach additional JavaScript functionality to standard APEX items.

Ext JS provides a rich library of sophisticated JavaScript components just waiting to be integrated into APEX using plug-ins.

A home for your plug-ins and dynamic actions

APEX allows you to create plug-ins for item, region, dynamic action, and process types. Like templates and themes, plug-ins are designed to be shared, so they can be easily exported and imported from one workspace application to another. Plug-ins can also be subscribed, providing a way to easily share and update common attributes between plug-ins.

Building a better Number Field

APEX 4.0 introduced the Number Field as a new item type, allowing you to configure number-range checks by optionally specifying minimum and maximum value attributes. It also automatically checks that the entered value is a number, and performs NOT NULL validation as well. You can also specify a format mask for the number as well, presumably to enforce decimal places.

This all sounds great, and it does work as described, but only after you have submitted the page for processing on the server.

The following screenshot shows the APEX and Ext versions of the Number Field, both setup with a valid number range of 1 to 10,000. The APEX version allows you to enter any characters you want, including letters. The Ext version automatically filters the keys pressed to only accept numbers, conditionally the decimal separator, and the negative sign. It also highlights invalid values when you go outside the valid number range.

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

We are going to build a better Number Field using APEX plug-ins to provide better functionality on the client side, and still maintain the same level of server-side validation.

The Number Field is quite a simple example, allowing us to be introduced to how APEX plug-ins work without getting bogged down in the details.

The process of building a plug-in requires the following:

  • Creating a plug-in in your application workspace
  • Creating a test page containing your plug-in and necessary extras to test it
  • Running your application to test functionality
  • Repeating the build/test cycle, progressively adding more features until satisfied with the result

Creating a plug-in item

For our Number Field, we will be creating an item plug-in.

So, navigate to the plug-ins page in Application Builder, found under Application Builder | Application xxx | Shared Components | Plug-ins, and press Create to open the Plug-in Create/Edit page.

Start filling in the following fields:

  • Name: Ext.form.NumberField. Here, I'm using the Ext naming for the widget, but that's just for a convenience.
  • Internal Name: Oracle's recommendation here is to use your organization's domain name as a prefix. So for example, a company domain of mycompany. com would prefix a plug-in named Slider, would result in an internal name of COM.MYCOMPANY.SLIDER.
  • File Prefix: As we are referencing the Ext JavaScript libraries in our page template, we can skip this field completely. For specialized plug-ins that are only used on a handful of specific pages, you would attach a JavaScript file here.
  • Source: For the PL/SQL source code required to implement our plug-in, you can either enter it as a PL/SQL anonymous block of code that contains functions for rendering, validating and AJAX callbacks, or refer to code in a PL/SQL package in the database.

You get better performance using PL/SQL packages in the database, so that's the smart way to go. Simply include your package function names in the Callbacks section, as shown in the following screenshot, noting that no AJAX function name is specified as no AJAX functionality is required for this plug-in. The package doesn't need to exist at this time—the form will submit successfully anyway.

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

Standard attributes:

In addition to being able to create up to ten custom attributes, the APEX team has made the standard attributes available for plug-ins to use. This is really useful, because the standard attributes comprise elements that are useful for most components, such as width and height. They also have items such as List of Values (LOV), which have more complicated validation rules already built-in, checking SQL queries used for the LOV source are valid queries, and so on.

For the Number Field, only a few attributes have been checked:

  • IsVisible Widget : Indicating the element will be displayed
  • Session State Changeable : So that APEX knows to store the value of the item in session state
  • Has Read Only Attribute : So that conditional logic can be used to make the item read only
  • Has Width Attributes : Allowing the width of the item to be set

Notice that some of the attributes are disabled in the following screenshot. This is because the APEX Builder conditionally enables the checkboxes that are dependent on another attribute. So, in this screenshot the List of Values Required, Has LOV Display Null Attributes, and Has Cascading LOV Attributes checkboxes are disabled, because they are dependant on the Has List of Values checkbox. Once it is checked, the other checkboxes are enabled.

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

Custom attributes:

Defining the custom attributes for our Number Field is largely an exercise in reviewing the configuration options available in the documentation for Ext.form.NumberField, and deciding which options are most useful to be included.

You need to also take into account that some configuration options are already included when you define an APEX item using your plug-in. For example, Item Label is included with an APEX item, but is rendered separately from the item, so don't need to be included. Likewise Value Required is a validation rule, and is also separate when rendering the APEX item.

The following next screenshot shows some Ext.form.NumberField configuration options, overlaid with the custom attributes defined in APEX for the plug-in:

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

I've chosen not to include the allowBlank config option as a custom attribute, simply because this can be determined by the APEX Value Required property. Other Configuration options, such as allowDecimals and allowNegative, are included as custom attributes as Yes/No types.

The custom attributes created are listed in the following table:

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

Custom events:

Custom events are used to define JavaScript event that can be exposed to dynamic actions. For this simple plug-in, there is no need to define any custom events. At this point, we are done defining the Number Field in APEX; it's time to turn our attention to building the database package to execute the Callbacks to render and validate the plug-in.

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: £20.99
Book Price: £33.99
See more
Select your format and quantity:
        Read more about this book      

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

Defining the plug-in Callback functions

Plug-ins must implement a fixed interface, defined for the plug-in type (item, region, dynamic action) and the Callback function (Render, AJAX, Validation).

For example, the item type plug-in Render Functions must implement the following interface:


function <name of function> (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin,
p_value in varchar2,
p_is_readonly in boolean,
p_is_printer_friendly in boolean )
return apex_plugin.t_page_item_render_result

So, for the Number Field plug-in, I'm using a package name plug_ext_form_numberfield , and function names render , ajax, and validate.

The PL/SQL package specification becomes:

CREATE OR REPLACE PACKAGE plug_ext_form_numberfield AS

function render (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin,
p_value in varchar2,
p_is_readonly in boolean,
p_is_printer_friendly in boolean )
return apex_plugin.t_page_item_render_result;

function ajax (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin )
return apex_plugin.t_page_item_ajax_result;

function validate (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin,
p_value in varchar2 )
return apex_plugin.t_page_item_validation_result;

END;
/

For the PL/SQL package body, we'll start out by building working stubs for the functions, and fill in the details, as we work through the solution.

CREATE OR REPLACE PACKAGE BODY plug_ext_form_numberfield AS

FUNCTION render (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin,
p_value in varchar2,
p_is_readonly in boolean,
p_is_printer_friendly in boolean )
return apex_plugin.t_page_item_render_result
IS
l_result apex_plugin.t_page_item_render_result;

subtype attr is
apex_application_page_items.attribute_01%type;

-- assign local names to attributes
l_allow_decimals attr := p_item.attribute_01;
l_allow_negative attr := p_item.attribute_02;
l_decimal_precision attr := p_item.attribute_03;
l_min_value attr := p_item.attribute_04;
l_max_value attr := p_item.attribute_05;
l_align attr := p_item.attribute_06;

-- Only use escaped value for the HTML output!
l_code varchar2(32767);
l_escaped_value varchar2(32767)
:= sys.htf.escape_sc(p_value);
l_name varchar2(30);
BEGIN
-- Debug information
if apex_application.g_debug then
apex_plugin_util.debug_page_item (
p_plugin => p_plugin,
p_page_item => p_item,
p_value => p_value,
p_is_readonly => p_is_readonly,
p_is_printer_friendly => p_is_printer_friendly );
end if;

if p_is_readonly or p_is_printer_friendly then
-- emit hidden field if necessary
apex_plugin_util.print_hidden_if_readonly (
p_item_name => p_item.name,
p_value => p_value,
p_is_readonly => p_is_readonly,
p_is_printer_friendly => p_is_printer_friendly );

-- emit display span with the value
apex_plugin_util.print_display_only (
p_item_name => p_item.name,
p_display_value => p_value,
p_show_line_breaks => false,
p_escape => true,
p_attributes => p_item.element_attributes );

else
-- If a page item saves state, we have to call the
-- get_input_name_for_page_item to render the internal
-- hidden p_arg_names field. It will also return the
-- HTML field name which we have to use when we render
-- the HTML input field.
l_name := apex_plugin.get_input_name_for_page_item(false);
sys.htp.p('<input type="text" name="'||l_name||
'" id="'||p_item.name||'" '||
'value="'||l_escaped_value||
'" size="'||p_item.element_width||'" '||
'maxlength="'||p_item.element_max_length||'" '||
coalesce(p_item.element_attributes,
'class="x-form-text"')||' />');


-- ****************************************************
-- @todo - write code for widget here
-- ****************************************************
l_code := 'Ext.onReady(function(){'||
'alert("@todo - write widget code");'||
'});';

-- Initialize page item when the page has been rendered.
apex_javascript.add_onload_code(p_code => l_code);

-- Tell APEX engine that field is navigable, in case
-- it's the first item on the page, and APEX page is
-- configured to navigate to first item (by default).
l_result.is_navigable := true;
end if;

return l_result;
END render;


FUNCTION ajax (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin )
return apex_plugin.t_page_item_ajax_result
IS
l_result apex_plugin.t_page_item_ajax_result;
BEGIN
-- @note - not using AJAX for this widget
-- usually logic goes here

-- not used by APEX yet
return l_result;
END ajax;


FUNCTION validate (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin,
p_value in varchar2 )
return apex_plugin.t_page_item_validation_result
IS
l_result apex_plugin.t_page_item_validation_result;
BEGIN
-- Debug information
if apex_application.g_debug then
apex_plugin_util.debug_page_item (
p_plugin => p_plugin,
p_page_item => p_item );
end if;

-- @todo - write validation code
return l_result;
END validate;

END plug_ext_form_numberfield;
/

Once the PL/SQL package specification and body has been compiled in the same schema as the parsing schema for the APEX Application, you have a fully functional "stub" for an item plug-in. The "stub" is a basic template pattern for item plug-ins; you simply insert the relevant code for your particular plug-in where the @todo comments are shown.

I'm not going to spend much time going through this PL/SQL code; that would be like "teaching your Grandmother how to suck eggs", as the saying goes.

There are a few important points worth noting though.

The APEX plug-in engine does a lot of work for you before it calls the plug-in code to render, validate, or execute AJAX processing on an item. The engine gathers the relevant metadata for the specific APEX page item, performing substitutions along the way before passing that information through to the plug-in as record-type parameters.

So, looking at the render function specification,

FUNCTION render (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin,
p_value in varchar2,
p_is_readonly in boolean,
p_is_printer_friendly in boolean )
return apex_plugin.t_page_item_render_result

you can see the the function is being passed record types apex_plugin.t_page_item and apex_plugin.t_plugin, and returning t_page_item_render_result.

The definitions for the record types are contained in the APEX_PLUGIN (APEX_040000.WWV_FLOW_PLUGIN) package specification, and include the following type declarations:

type t_plugin is record (
name varchar2(45),
file_prefix varchar2(4000),
attribute_01 varchar2(32767),
...
attribute_10 varchar2(32767) );

type t_page_item is record (
id number,
name varchar2(255),
label varchar2(4000),
plain_label varchar2(4000),
format_mask varchar2(255),
is_required boolean,
lov_definition varchar2(4000),
lov_display_extra boolean,
lov_display_null boolean,
lov_null_text varchar2(255),
lov_null_value varchar2(255),
lov_cascade_parent_items varchar2(255),
ajax_items_to_submit varchar2(255),
ajax_optimize_refresh boolean,
element_width number,
element_max_length number,
element_height number,
element_attributes varchar2(2000),
element_option_attributes varchar2(4000),
escape_output boolean,
attribute_01 varchar2(32767),
...
attribute_10 varchar2(32767) );

type t_page_item_render_result is record (
is_navigable boolean default false,
navigable_dom_id varchar2(255) );

As you can see, there is a fairly substantial amount of metadata available for you to use when generating code for your plug-in.

One of the utility procedures most useful when starting out building your plug-in is the debugging procedure, called using the following code:

if apex_application.g_debug then
apex_plugin_util.debug_page_item (
p_plugin => p_plugin,
p_page_item => p_item );
end if;

With debugging enabled for a page containing your plug-in, the debugging page shows the parameters values being passed to your plug-in package, as can be seen in the following screenshot:

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

At this point, it's a good time to create a page and include the number plug-in, so we can do some testing and progressively add functionality to the plug-in.

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: £20.99
Book Price: £33.99
See more
Select your format and quantity:
        Read more about this book      

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

Creating a page item based on the Number Field plug-in

Creating a page item based on your plug-in is done exactly the same way you would any standard APEX item. Simply create the item, then select your plug-in under the Display option , and start filling in the details for the item as usual.

The standard attributes available are determined by the plug-in definition; we didn't select the standard attribute Has List of Values for the plug-in earlier, so that section isn't available for our Number Field. The custom attributes we defined for the Number Field appear in the Settings section, as you can see in the following screenshot:

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

So, go ahead and create a test page with your shiny new Number Field plug-in, and give it a test run. If everything is working as expected, then it should look and behave exactly like a standard APEX Text Field. It will accept any text you enter, submit and store the result in Session state, and render it as a read-only field if you set the Read-Only Condition.

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

The only inconvenient thing about it is that annoying JavaScript alert shown in preceding screenshot, reminding us that we haven't finished writing the plug-in source. Let's remedy that now.

Render functionality for the Number Field plug-in

Our stub function already includes enough logic to behave as a standard APEX Text field. To make it behave as an Ext.form.NumberField, providing automatic keystroke filtering and number validation, we need to generate JavaScript code to convert it.

The generated JavaScript will look similar to the following:

Ext.onReady(function(){
new Ext.form.NumberField({
applyTo: 'P120_NUMBER_FIELD',
allowDecimals: false
allowNegative: false,
decimalPrecision: 2,
minValue: 1,
maxValue: 10000,
value: 54
});
});

You can easily test this on your test page by pasting the preceding code into the Firebug console in Firefox, changing the applyTo value to match your page item, and running it.

Looking at the generated JavaScript, it's readily apparent that the code generator simply needs to build up the text, adding the parameters and dynamic values as it goes.

The final version of the render function is as follows:

FUNCTION render (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin,
p_value in varchar2,
p_is_readonly in boolean,
p_is_printer_friendly in boolean )
return apex_plugin.t_page_item_render_result
IS
l_result apex_plugin.t_page_item_render_result;

subtype attr is
apex_application_page_items.attribute_01%type;

-- assign local names to attributes
l_allow_decimals attr := p_item.attribute_01;
l_allow_negative attr := p_item.attribute_02;
l_decimal_precision attr := p_item.attribute_03;
l_min_value attr := p_item.attribute_04;
l_max_value attr := p_item.attribute_05;
l_align attr := p_item.attribute_06;

-- Only use escaped value for the HTML output!
l_code varchar2(32767);
l_escaped_value varchar2(32767)
:= sys.htf.escape_sc(p_value);
l_name varchar2(30);

To improve the readability of your code, it's worthwhile assigning the p_item attribute value s to local variables.

Also highly recommended is escaping any values passed from the HTML page using the Oracle provided sys.htf.escape_sc function to prevent SQL injection attacks. A malicious person can easily circumvent any HTML page protection using developer tools, such as Firebug, to force the page to submit SQL injection text.

BEGIN
-- Debug information
if apex_application.g_debug then
apex_plugin_util.debug_page_item (
p_plugin => p_plugin,
p_page_item => p_item,
p_value => p_value,
p_is_readonly => p_is_readonly,
p_is_printer_friendly => p_is_printer_friendly );
end if;

if p_is_readonly or p_is_printer_friendly then
-- emit hidden field if necessary
apex_plugin_util.print_hidden_if_readonly (
p_item_name => p_item.name,
p_value => p_value,
p_is_readonly => p_is_readonly,
p_is_printer_friendly => p_is_printer_friendly );

-- emit display span with the value
apex_plugin_util.print_display_only (
p_item_name => p_item.name,
p_display_value => p_value,
p_show_line_breaks => false,
p_escape => true,
p_attributes => p_item.element_attributes );

else
-- If a page item saves state, we have to call the
-- get_input_name_for_page_item to render the internal
-- hidden p_arg_names field. It will also return the
-- HTML field name which we have to use when we render
-- the HTML input field.
l_name := apex_plugin.get_input_name_for_page_item(false);
sys.htp.p('<input type="text" name="'||l_name||
'" id="'||p_item.name||'" '||
'value="'||l_escaped_value||
'" size="'||p_item.element_width||'" '||
'maxlength="'||p_item.element_max_length||'" '||
coalesce(p_item.element_attributes,
'class="x-form-text"')||' />');

The first section of the procedure remains exactly the same as the earlier version. Now we remove the stubbed code:

-- ****************************************************
-- @todo - write code for widget here
-- ****************************************************
l_code := 'Ext.onReady(function(){'||
'alert("@todo - write widget code");'||
'});';

The stubbed code is replaced with the following highlighted code:

-- build Ext.form.NumberField properties
l_code := wwv_flow_javascript.add_attribute(
'applyTo', p_item.name)
||wwv_flow_javascript.add_attribute(
'allowDecimals'
,case when l_allow_decimals = 'N' then 'false' end)
||wwv_flow_javascript.add_attribute(
'allowNegative'
,case when l_allow_negative = 'N' then 'false' end)
||wwv_flow_javascript.add_attribute(
'decimalPrecision', l_decimal_precision)
||wwv_flow_javascript.add_attribute(
'minValue',l_min_value)
||wwv_flow_javascript.add_attribute(
'maxValue',l_max_value)
||wwv_flow_javascript.add_attribute(
'value',l_escaped_value);

-- can't use add_attribute() as it escapes double quotes
if l_align is not null then
l_code := l_code||'"style": {"text-align":"'
||l_align||'"},';
end if;

l_code := l_code||wwv_flow_javascript.add_attribute(
p_name => 'ajaxIdentifier',
p_value => apex_plugin.get_ajax_identifier,
p_add_comma => false);

l_code :=
'Ext.onReady(function(){new Ext.form.NumberField({'
||l_code||'});});';

-- Initialize page item when the page has been rendered.
apex_javascript.add_onload_code(p_code => l_code);

-- Tell APEX engine that field is navigable, in case
-- it's the first item on the page, and APEX page is
-- configured to navigate to first item (by default).
l_result.is_navigable := true;
end if;

return l_result;
END render;

The highlighted code shows the changes to the stubbed version, simply replacing the alert message with the final JavaScript we want, dynamically assigning the property values using the APEX items metadata. Once again, APEX has provided utilities in the APEX_JAVASCRIPT (APEX_040000.WWV_FLOW_JAVASCRIPT) package to simplify the process.

Validation functionality for the Number Field plug-in

Currently, the validation function for the Number Field plug-in does absolutely nothing; it's just a stub that compiles and nothing more. Even so, APEX does some validation for us, checking for mandatory items.

The final code for the validation function verifies the page item value is a number with a value conforming to the rules specified for the page item:

FUNCTION validate (
p_item in apex_plugin.t_page_item,
p_plugin in apex_plugin.t_plugin,
p_value in varchar2 )
return apex_plugin.t_page_item_validation_result
IS
subtype attr is
apex_application_page_items.attribute_01%type;

-- assign local names to attributes
l_allow_decimals attr := p_item.attribute_01;
l_allow_negative attr := p_item.attribute_02;
l_precision number := to_number(p_item.attribute_03);
l_min_value number := to_number(p_item.attribute_04);
l_max_value number := to_number(p_item.attribute_05);

n number;
l_result apex_plugin.t_page_item_validation_result;
BEGIN
-- Debug information
if apex_application.g_debug then
apex_plugin_util.debug_page_item (
p_plugin => p_plugin,
p_page_item => p_item );
end if;

-- Nothing to do when null (APEX checks for mandatory items)
if p_value is null then return l_result; end if;

-- verify value is numeric
begin
n := to_number(p_value);
exception
when value_error then
l_result.message := 'Value for '||
p_item.plain_label||' must be a number';
return l_result;
end;

case when l_allow_decimals = 'N' and n <> trunc(n) then
l_result.message := 'Decimals not allowed for '||
p_item.plain_label;
when l_precision is not null
and n <> trunc(n,l_decimal_precision) then
l_result.message := 'Decimals places cannot exceed '||
l_precision||' for '||p_item.plain_label;
when l_allow_negative = 'N' and n <> abs(n) then
l_result.message := 'Negative numbers not allowed'||
' for '||p_item.plain_label;
when l_min_value is not null and n < l_min_value then
l_result.message := 'The minimum value for '||
p_item.plain_label||' is '||l_min_value;
when l_max_value is not null and n > l_max_value then
l_result.message := 'The maximum value for '||
p_item.plain_label||' is '||l_max_value;
else null;
end case;

-- return l_result with error message, success => null
return l_result;
END validate;

That wraps up the implementation for the Number Field Plug-in.

Summary

In this article, we have covered the development process for creating an item type plug-in, showing how to define the plug-in and its parameters in APEX. We initially created a "stub" PL/SQL package for the Plug-in, allowing us to create a test page for our Plug-in and start using it as a standard APEX text item. Once the stub was working, we then were able to add in the enhanced JavaScript functionality progressively on the web page, before completing the Plug-in by adding the server-side validation.

Since the NumberField is just enhancing a standard HTML input field and does not add additional HTML elements, the standard Dynamic Actions will work quite happily without change. We haven't implemented any AJAX functionality because there hasn't been any requirement.


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


Learning Ext JS 3.2
Learning Ext JS 3.2

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

Linux Shell Scripting Cookbook
Linux Shell Scripting Cookbook

Scribus 1.3.5: Beginner's Guide
Scribus 1.3.5: Beginner's Guide

XNA 4.0 Game Development by Example: Beginner's Guide
XNA 4.0 Game Development by Example: Beginner's Guide

Oracle APEX 4.0 Cookbook
Oracle APEX 4.0 Cookbook

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