Monday, 23 December 2013

Creating ReForms in Oracle APEX


Let me begin by defining a ReForm. A ReForm is an amalgum of Reports and Forms and has the DNA of both. This discussion not only presents a ReForm but also demonstrates the enormous benefits of using JQuery in APEX report development.
I wish to state that this article is borrowed from my book on Oracle APEX 4.2 Reporting. You can check the table of contents and a brief description of the book along with the screenshots.

Let me first share the final result of our exercise. Note that the underlining red lines are just to highlight the feature of ReForms and are not a result of the code.
In this post, we will learn the process to create a ReForm (Report cum Tabular Form) and will also see the process of controlling the data cells for superior reporting. ReForms can not only help us put advanced JQuery validations but can also selectively disable the editing of some of the data cells.

I call it a ReForm (Report cum Tabular Form) because the initial outlook of this product looks like a REPORT and the data cells get converted to text fields as soon as a user clicks on them. The user gets the freedom to edit multiple rows and columns just the way she can in a Tabular FORM.

I have created an example to help you get a first hand experience of the product. The example is available  @ https://apex.oracle.com/pls/apex/f?p=81782:6:0:::::
The code has been tested in Internet Explorer 8, Google Chrome version 31 and Firefox 24.0.  

Click on any data cell which you want to edit and you will see that the data cell gets converted to a text field. The value in the data cell is fed to the text field and you can then hit the submit button to save the edited value. Any number of data cells can be edited and the changed values appear as a Report. Hence the name Re(port)Form.

Let us now understand the steps of implementing a ReForm.

1. Create a Tabular Form that updates the data. Note that we are initiating the process by creating a Tabular Form because creating a Tabular Form creates the necessary DML page processes in APEX.
2. Change the value in the Display As dropdown to Display as Text (saves state) for every column. This will ensure that the default look and feel of a ReForm is that of a Report.
3. Create a Dynamic Action that
          a. Has Click in the Event dropdown
          b. Has jQuery Selector in the Selection Type dropdown
          c. Has .data in jQuery Selector text field. Note that I am putting .data in the jQuery Selector text field because data CSS class is used by my theme to format the values in my report. If your theme uses a different class then replace .data with .<your_class_name_without_angle_brackets>. Let me show you a screenshot of the HTML source of my page. Note the highlighted data class in the below screenshot.
           d. Has your tabular region (created in Step 1) as the value in the Affected Elements section.
           e. Executes the following code when the DA is triggered

var oldHTML = $(this.triggeringElement).html();
var oldHTML_lower = oldHTML.toLowerCase();
var arr;
var arr2;
var lab;
if( oldHTML.indexOf( "<span" ) != -1 )
{arr = oldHTML.split('<span');
arr2 = arr[1].split('</span>');}
if( oldHTML.indexOf( "<Span" ) != -1 )
{arr = oldHTML.split('<Span');
arr2 = arr[1].split('</Span>');}
if( oldHTML.indexOf( "<SPAN" ) != -1 )
{arr = oldHTML.split('<SPAN');
arr2 = arr[1].split('</SPAN>');}
if (oldHTML.indexOf('maxlength') == -1 && oldHTML.indexOf('type=text') == -1 )
{
var name = $(this.triggeringElement).children().attr('name');
var id = '';
$(this.triggeringElement).children().each(function(i){if(this.id && id==''){id = this.id;}});
var val = $(this.triggeringElement).children().attr('value');
lab = oldHTML.substr(oldHTML_lower.indexOf('<label'),oldHTML_lower.indexOf('</label>')-oldHTML_lower.indexOf('<label')+8);
var final_html = lab + '<INPUT id="'+id+'" value="'+val+'" maxLength=2000 size=16 type=text name="' + name + '" autocomplete="off">'+arr2[1];
$(this.triggeringElement).html(final_html);
}

Let us try to understand this code now.

We have defined our Dynamic Action such that any click on a HTML element that has the data class in its class attribute triggers the DA. Since every data cell in the ReForm is formatted by the data class, the click on any data cell triggers the Dynamic Action.

$(this.triggeringElement).html();, at the top of the above code, helps us to capture the HTML of the data cell on which the user clicks. We then perform a series of operations to extract the label, the id, the value and the name associated with the data cell. We then use this information to create a text field. Since we use the id and other attributes of the old HTML, APEX's DML page process does not have any trouble in processing the rows. We assign our new modified HTML to final_html variable and then use $(this.triggeringElement).html(final_html); to make sure that the change is reflected on the browser.
The above code also has the following if statement.
if (oldHTML.indexOf('maxlength') == -1 && oldHTML.indexOf('type=text') == -1 )
This statement ensures that the code is not triggered if the data cell has already been converted to a text field. So a second click on the same data cell does not fiddle with the text field and the value in it.

The processing after the user edits the value and hits the Submit button happens just the way the processing happens for a usual Tabular Form.

Let me know if you want me to elaborate on any point

Dont forget to check the the table of contents and a brief description along with the screenshots of my book on Oracle APEX 4.2 Reporting that has many more discussions like this.

http://obiee-oracledb.blogspot.in/2013/12/creating-dynamic-breadcrumb-chains-in.html and http://obiee-oracledb.blogspot.in/2013/12/data-densification-in-oracle-apex.html blog posts are also inspired from the sample chapter of my book on Oracle APEX 4.2 Reporting and might interest you.

Cheers

No comments: