Open UI

Siebel Open UI: Format All the Lists – Part 2

In continuation of our mini-series, we will today explore an example solution for a generic physical renderer extension for list applets in Siebel Open UI.

As discussed in the previous part, the solution we want to achieve is that we can define a list of fields which should be conditionally formatted if they are exposed as columns on a list applet. The implementation uses custom applet user properties which are exposed to the physical renderer by a custom presentation model extension.

Today, the focus is on the physical renderer. Before we start, let me reiterate that many ways lead to Rome and the solution presented below is purely educational and should you intend to use it in any environment, including production environments, you do so at your own risk.

Implementing a Physical Renderer for Conditional Formatting

We start with the usual procedure of creating a physical renderer extension file and registering it with a test applet (e.g. the Opportunity List Applet). Remember that the Oracle class for list applet PRs is JQGridRenderer, so this is the correct call for SiebelJS.Extend():

SiebelJS.Extend(ConditionalFormatListPR, SiebelAppFacade.JQGridRenderer);

As the formatting takes place when the data is present in the applet, the BindData method is the one we must override, as this method populates the grid cells with the actual data and is called frequently enough (e.g. after a record is updated or during scrolling) for a first prototype.

The following shows the example implementation of the BindData method:

Click to enlarge.

The code accomplishes the following:

  • Initialize variables with the values of the applet user properties by using the PM’s Get method.
  • Verify that a list of fields is actually defined for the applet. If yes, the code continues. If not, the else block is reached and a console message is logged.
  • Split the comma separated lists into arrays using the split function.
  • Use the GetColMap method of the object returned by the GetColumnHelper method to get a list of columns and their respective business component field names. Note that the two methods used here are specific to physical renderers for list applets and are not documented.
  • Iterate through the array of fields. For each field, a second loop iterates through the column list and tries to locate a column associated with that field. When a column is found, the ConditionalFormat method (to be implemented below) is invoked and the name of the column as well as the accompanying threshold value are passed as arguments.

The following is the first part of the custom ConditionalFormat function which actually handles the formatting.

Click to enlarge
This part of the custom function does the following:
  • Get the current record set from the GetRecordSet property, i.e. all records currently visible in the list applet.
  • Get the applet placeholder which will be used to identify the applet and its child elements.
  • Get the column map for the applet.
  • Retrieve the business component field name for the current column from the column map.
  • Access the column header using the jQuery $() function.
  • Use the jQuery click() event handler to specify a function which is executed when the end user clicks the column header. This function uses the event object to determine whether the CTRL key has been pressed while clicking. If this is the case, the click event handler function uses the stopImmediatePropagation() method to prevent the click event from “bubbling”, i.e. attracting other event handlers.
  • For demonstration purposes, a simple prompt() dialog is used to solicit the new target value from the end user. This could be replaced by a more comfortable jQuery dialog or similar in a real production setting. Finally, the click event handler function invokes the ConditionalFormat method (recursively) to refresh the formatting.
  • By adding an img tag to the existing column header HTML code, the function effectively provides a visual cue to the end user that the column and its header have a special purpose. The example code also modifies the title attribute to produce a tooltip message.
Now that we have all variables initialized and the column header modified, we can implement a loop through the record set to take care of each cell’s background color:
Click to enlarge.
This final loop does the following:
  • Retrieve the pseudo row identifier (1,2,3 and so forth).
  • Select the current row using the jQuery find method.
  • Select the grid cell for the column.
  • Retrieve the cell’s value, which is actually the formatted and localized value.
  • Use the replace function to remove characters like $, % or commas from the value string (watch out for localization issues here, the example is for the ENU locale).
  • Convert the string to a floating point number.
  • Calculate the share of the current value in percent of the target (threshold) value.
  • Calculate the green and red color components for the current share. The algorithm increases the green value until the share reaches 50% and then reduces the red value. This results in a red/yellow/green color gradient.
  • Use the calculated color to set the background of the cell with the jQuery css() method. For compatibility reasons the example code shows how to set a solid background as well as use the vendor specific linear-gradient CSS rules. A browser which understands the linear-gradient rule will apply it, other browsers will show a solid background.
After correctly associating this physical renderer example with a test list applet which has the necessary user properties defined, we can verify that the behavior is expected. Here is a screenshot of the sales order list applet after specifying the NRC Total field for conditional formatting.
Click to enlarge.
After the test with a single list applet, we can modify the manifest administration to use the DEFAULT LIST APPLET entry for a physical renderer. Be aware that even the slightest error in the custom code could render any list applet unusable, including the ones you would need to undo your changes. If you find yourself in this undesirable situation, either rename the custom JavaScript file, so the browser can’t download it or use the High-Interactivity client to access the Manifest Administration view.
Summary
The educational example in this and the previous article demonstrates the possibility of writing generic presentation model and physical renderer extensions for list applets. By externalizing as much code as possible we can limit the amount of code to achieve a consistent behavior across all UI objects of the same type.
Full Code Examples
The full code examples (for IP 2013 or higher) are available for download:
have a nice day
@lex

Siebel Open UI: Default Applet Override

One of the lesser known facts about Siebel Open UI – as of Innovation Pack 2013 which introduced database-stored manifest data – is that we can not only register JavaScript files (or web templates) with specific user interface objects but also create default entries for them, so the files will be loaded for each object of the same type. Something we could call a “global override”.

Using a global override is superior to using the postload event handler which might soon become bloated with all the stuff you want to achieve on non-specific objects.

Recently, I had some time to investigate this feature a bit more closely. Some of my dear readers might remember the “See-Through Applets” which involves a double-click event handler. When a form applet is double-clicked, the labels are replaced with metadata from the business component layer. Another double click reveals the table and column names where the data is stored. The final solution I presented used a postload event handler.

You can find a detailed description of the see-through applets here and here.

Siebel form applet in “see-through” mode 😉

So let’s see how I adjusted the see-through applet code to work with a global override. The goal was again to enable the functionality on every form applet with a minimum effort.

1. Create a physical renderer extension

The first thing I did was to create a physical renderer extension file. Just the “normal” thing

2. Register the custom file as a default entry

Next, I followed the usual steps to register the file in the Manifest Files view of the Administration – Application screen.

In the Manifest Administration view, the big difference was to query for the seeded DEFAULT FORM APPLET entries in the UI Objects list and copy the existing entry for the Physical Renderer usage type.

Then I proceeded to add an expression and my custom file (as usual). Here is the result:

Click to enlarge

The Open UI framework will read all entries and ensure that the as-delivered files and the custom overrides are loaded whenever a form applet needs to be renderered.

3. Implement the double-click handler

Now I was able to migrate the code which defines the double-click functionality from my custom postload event handler to the new default physical renderer extension’s ShowUI method. In fact I could comment out some lines as it was no longer necessary to establish a “connection” to the form applet. Another benefit of staying inside the framework 😉

The ShowUI method of the override physical renderer. Click to enlarge.

4. Test

I retired (i.e. commented out) the code in the postload event handler and reloaded the browser cache and voilá, the same as before but without extraneous code in the postload event handler.

Summary

“Global overrides” or default entries are a great alternative to clogging your postload event with JavaScript code. At the time of writing, there are various seeded default entries for form, list and tree applets which you should copy to create your custom default entry. Future versions might see other default entries such as for views.

have a nice day

@lex

TEL/電話+86 13764045638
Email service@parnassusdata.com
QQ 47079569