The Pentaho Prompting component of the Pentaho Common UI project defines a set of JavaScript APIs to create a collection of components, or prompts, based on a Parameter XML Specification. It was built from the ground up to allow easy extensibility for custom prompt component types and relies on Pentaho CDF to provide the foundation for which the components are defined and how the prompting panel can be interacted with by the user.
Project Location
The Pentaho Prompting API was introduced in Pentaho Common UI version 1.0.2 and is included in the BI Server 4.5+.
The source is part of the Pentaho Common UI project and can be found here:
svn://source.pentaho.org/svnroot/platform-plugins/common-ui/trunk/package-res/resources/web/prompting
In a running Pentaho BI Server you can find JavaScript unit tests here:
http:///pentaho/content/common-ui/resources/web/test/unittest/TestRunner.html
Sample Prompt
A simple working example is provided as part of the Pentaho Prompting project in a running BI Server:
http:///pentaho/content/common-ui/resources/web/prompting/sample.html
You can use this page to experiment with different settings by manipulating the parameter xml that drives the prompt.
Module Overview
The Prompt Panel API is built on top of the concept of modules and relies on RequireJS, a modular script loading mechanism, to load the scripts dynamically at runtime*. With it you can write JavaScript that will execute when a list of modules (dependencies) have been loaded. For more information on using RequireJS and modules see http://requirejs.org/docs/whyamd.html. Refer to the sample page for an example of how to include the prompting modules on your page. The Custom Components section will detail how to leverage the module loading system to define your own components.
The following modules exist in Pentaho Prompting API:
Name |
Description |
common-ui/prompting/pentaho-prompting |
Main Pentaho Prompting APIs: PromptPanel, ParameterXmlParser, ParameterDefinition and associated objects (ParameterGroup, Parameter, ParameterValue, ..) |
common-ui/prompting/pentaho-prompting-builders |
Widget Builder API and implementations for the standard components |
common-ui/prompting/pentaho-prompting-components |
Widget component implementations |
common-ui/prompting/pentaho-prompting-bind |
Function.bind() declaration |
* RequireJS can also be used to build compressed JavaScript builds and is how the Report Viewer builds its client-side application.
Parameter XML Parser
The Pentaho Prompting JavaScript API relies on a Parameter Definition to control its layout and behavior. Included in the project is a Parameter XML Parser designed to convert XML that conforms to the Parameter XML Specification into a pentaho.common.prompting.ParameterDefinition.
The API is fairly straight forward. Given xmlString, the parameter xml, we're able to parse it into a parameter definition using the included parameter xml parser:
var xmlString = '<?xml version="1.0" encoding="UTF-8"?><parameters accepted-page="0" autoSubmitUI="true" ... var parser = new pentaho.common.prompting.ParameterXmlParser(); var parameterDefinition = parser.parseParameterXml(xmlString);
Prompt Panel
The core of Pentaho Prompting is the panel that contains all the UI components that allow a user to interact with it. The layout is controlled by a pentaho.common.prompting.ParameterDefinition
. The Parameter XML Specification component types are mapped to Pentaho CDF components defined in the CDF project itself, the prompting project, or any custom components. A parameter is mapped to a CDF component by it's "type" attribute. The pentaho.common.prompting.builders.WidgetBuilder
is responsible for mapping and building components for a given parameter type.
Creating a Prompt
To create a prompt panel from a parameter definition you can use the following code:
var promptPanel = new pentaho.common.prompting.PromptPanel('promptPanelElementId', parameterDefinition); // Called on auto-submit or submit button click promptPanel.submit = function() {...}; // Called on schedule button click promptPanel.schedule = function() {...}; // Called when parameters changed to support cascading prompts promptPanel.getParameterDefinition = function() {...}; // Initialize the prompt, building it and injecting it into the DOM at 'promptPanelElementId' promptPanel.init();
Prompting API
The following methods can be overridden to customize the prompt panel:
pentaho.common.prompting.PromptPanel
:
submit = function()
called when auto-submit is triggered or the user manually triggers the submit button.schedule = function()
: called when the schedule button is triggered.getParameterDefinition = function(paramPanel, callback)
: This is provided as a way to dynamically update the parameter definition based on new input. This allows for the implementation of cascading parameters. It is called whenever a parameter's value changes. TheparamPanel
argument is the panel which is being updated and thecallback
is the refresh function which should be called with the updated parameter definition to refresh the prompt panel.createDataTransportFormatter = function(paramDefn, parameter, pattern, formatter)
: This should return an object capable of formatting an object to the format used to send over the wire (the format it is transported in).getString = function(key, defaultString)
: Used for i18n. The default implementation always returns the default string. Override to provide custom i18n support.
Custom Components
The Pentaho Prompting UI relies on a set of builders to create all the components that make up the prompt. From the panels that lay out the components to the input components themselves. All of this is funneled through pentaho.common.prompting.builders.WidgetBuilder
. The builder is responsible for creating an object that represents a Dashboards component.
Creating a custom component
The most simple CDF component can be described as an object with an update()
function. When Dashboards initializes, and on every refresh, it calls update()
on all its components.
Here's a simple component that appends " (My Custom Component)" to all labels of a prompt.
var MySimpleComponent = Base.extend({ update: function() { $('#' + this.htmlObject).html(this.label + ' (My Custom Component)'); } });
*Note: this.htmlObject
is by convention the ID of the element where the component should be injected.
Creating a custom component builder for our custom component
For this example let's say we want to replace the default label component used to describe all prompt labels with our custom component. In order to do so we'll override the existing builder for our label component type and generate objects that describe our new custom component. Dashboards will take care of turning these metadata objects into the actual components.
WidgetBuilder.build(args, typeOverride)
should create a metadata object describing a component. The typeOverride
allows for the component type to be explicitly specified. If not, the args.param.attributes["parameter-render-type"]
value is used to look up a builder in the WidgetBuilder.mapping
map which should be capable of creating a metadata object describing a component of the desired type.
The args
argument to WidgetBuilder.build(args, typeOverride)
is a hash of key/value pairs providing hints and information for the builder. Common key/values that you can expect to exist for any call to build()
are:
promptPanel
: the prompt panel this component is being built forparam
: the parameter this component is being built for
Finally, here's an example of a custom builder to create a MySimpleComponent
(as defined above) for all components of type 'label':
/** * Define a custom component that replaces the exiting label component. This must be a named module. * * See http://requirejs.org/docs/api.html#modulename for more information. */ pen.require( // We require the Prompting Builder API to be loaded as we'll replace the existing label builder with ours ['dojo', 'common-ui/prompting/pentaho-prompting-builders'], function() { window.MySimpleComponent = Base.extend({ update: function() { $('#' + this.htmlObject).html(this.label + ' (My Custom Component)'); } }); window.MyCustomBuilder = pentaho.common.prompting.builders.ParameterWidgetBuilderBase.extend({ build: function(args) { var widget = this.base(args); // Change the name and htmlObject to append -label so we don't conflict with the input component for this parameter widget.name = widget.name + '-label'; widget.htmlObject = widget.name; widget.type = 'MySimpleComponent'; widget.label = args.param.attributes['label']; return widget; } }); // Replace the label component builder with ours pentaho.common.prompting.builders.WidgetBuilder.mapping['label'] = 'MyCustomBuilder'; });
Sample components are registered via the plugin's plugin.xml
as external resources. A working sample component can be found here:
http://source.pentaho.org/svnroot/platform-plugins/common-ui/trunk/package-res/resources/web/prompting/pentaho-prompting-sample-component.js
And it is registered through Common UI's plugin.xml
here (found in the common-ui/ plugin directory in a working installation):
http://source.pentaho.org/svnroot/platform-plugins/common-ui/trunk/package-res/plugin.xml
Formatting Values
Pentaho Prompting was created to serve as a basis for the Pentaho Reporting Web Viewer. The Pentaho Reporting Engine requires parameters to adhere to a specific format. To bridge the gap between CDF component's internal formats and what the reporting engine expects we must format values into at least 2 different formats: wire format and display format.
To facilitate this we've provided a java.text.Format compatible formatter via GWT with a clean JavaScript API. This is known as the JSTextFormatter and is available under the global variable jsTextFormatter
once loaded.
The source is located in the Pentaho GWT Widgets project:
svn://source.pentaho.org/svnroot/pentaho-commons/pentaho-gwt-modules/trunk/pentaho-gwt-widgets/src/org/pentaho/gwt/widgets/client/formatter
The GWT module is available in a Pentaho BI Server in the Pentaho Common UI project:
<script type="text/javascript" src="/pentaho/content/common-ui/resources/web/formatter/formatter.nocache.js"></script>
There are two methods defined for a formatter: parse
and format
that are analogous to the similarly named methods defined for java.text.Format.
Sample Number Formatter
var numberFormatter = jsTextFormatter.createFormatter('number', '$#.0#'); var number = 123.45; var formatted = numberFormatter.format(number); alert('Formatted number object: ' + number + ' -> ' + formatted); var parsed = numberFormatter.parse(formatted); alert('Parsed string: ' + formatted + ' -> ' + parsed);
Sample Date Formatter
var dateFormatter = jsTextFormatter.createFormatter('date', 'yyyy-MM-dd HH:mm'); var date = new Date(); var formatted = dateFormatter.format(date); alert('Formatted date object: ' + date + ' -> ' + formatted); var parsed = dateFormatter.parse(formatted); alert('Parsed string: ' + formatted + ' -> ' + parsed);