Profound UI Version 6 Fix Pack 12.0 adds a feature allowing custom widgets to fully and more easily integrate with Profound UI. Consequently, custom or 3rd party widgets from other frameworks can be made to work with Profound UI and be treated like native Profound UI widgets:
- input data from custom widgets submits to the server-side program just like data from Profound UI widgets
- the widgets can be rendered inside grids, and their values get sent back to the server-side program as subfile data
- most Profound UI Widget APIs work with them.
Additionally, custom properties for custom widgets can be configured as bidirectional–that is, both input and output. In the past, only a custom widget's "value" property could be used for input. Now, any custom property can be use for input. Additionally, multiple properties can be used for input on a single custom widget.
The new pui.BasicWidget class simplifies the task of creating custom widgets without sacrificing any flexibility.
To use the new bidirectional properties in custom widgets, there are two API that now accept special arguments:
- pui.widgets.add - the "constr", "render", and "getValue" options are added for pui.BasicWidget. The "render" and "getValue" options for pui.widgets.add may be sufficient for most needs. For more advanced use, the constructor of a subclass of pui.BasicWidget can be specified for "constr".
- pui.addCustomProperty - the "bidirectional" and "showDesignValue" options are added for pui.BasicWidget
pui.BasicWidget is a class defined in Profound UI that integrates with the Profound UI framework allowing input and output and point-and-click design. pui.BasicWidget is designed for Object-Oriented-Programming so that code can be encapsulated and inherited for reuse. Custom widgets that subclass pui.BasicWidget can render not just in runtime, but in Visual and Node Designers for visual, WYSIWYG screen design.
When widgets are added to Profound UI using the "render" and "getValue" options to pui.widgets.add, the widgets automatically become instances of pui.BasicWidget. The render and getValue functions get assigned and bound to the pui.BasicWidget class so that the special word, "this", refers to the class instance.
In the call to pui.widgets.add there is no need to define a "propertySetters" option or a "globalPropertySetter" function when using pui.BasicWidget. In fact, pui.BasicWidget assigns its own "globalPropertySetter" in order to handle when Profound UI changes the widget by setting properties.
When a pui.BasicWidget is constructed a reference to it is placed in the DOM as a "widget" property inside the "pui" object. For example, you could reach a pui.BasicWidget by doing something like: var myWidget = getObj("MyWidgetId1").pui.widget;
These methods can be defined or overridden in child classes. Code that exists outside the pui.BasicWidget class should not normally call these functions directly, excepting "render". Instead, use Profound UI widget APIs to change property values when necessary.
- render (required) - A function that Profound UI calls after all of the widget properties are set. Either pui.BasicWidget subclasses must define "render", or the "render" supplied to the call to pui.widgets.add must define it. If custom code calls the API, applyProperty to change a pui.BasicWidget property, then "render" should also be called to refresh the widget. Do not use applyProperty(..., "field type", ...) to redraw the widget, because calling "field type" will destroy and re-create the widget.
- getValue (required) - A function that Profound UI calls to get the current value of a property. Argument: a string, property name; e.g. "value", "user defined data", "label". If this function is not defined in subclasses or in the call to pui.widgets.add, then the default behavior is: return evalProperty(propname); This function should extract the necessary information from a custom widget's DOM and return it as a string. The returned string later gets formatted according to the bound data type and format.
- cleanup - A function that can be defined in sub-classes. "cleanup" is called when the widget is destroyed, after the screen has submitted and before a new screen renders. If the render function added any event listeners, then those listeners should be removed in "cleanup".
- evalProperty - A function that evaluates the current value of a property as set by a Profound UI property. There is one String parameter, the property name being set. Using "evalProperty" is helpful in Genie Design Mode. "evalProperty" can handle properties of type, "script", set with "js: ...somecode...". Subclasses normally need not override "evalProperty", but if they do they must call the version in pui.BasicWidget.prototype first; e.g. before any other code do: pui.BasicWidget.prototype.evalProperty.call(this, propname);
- handleEvent - A function that accepts an Event parameter and does "this.dom.modified = true;" if the event type is "input" or "change". In order for "handleEvent" to run, event listeners must be added in the "render" or "setProperty" functions like so: someCustomElement.addEventListener('change', this); or someCustomElement.addEventListener('input', this); . Sub-classes can override the super-class's "handleEvent", and there is no need to call the super-class "handleEvent". Note: "this.dom.modified = true;" must happen when a value has changed in the custom widget; otherwise, without the "modified" flag Profound UI will not send the widget data to the server-side program.
- setProperty - A function that can be defined in subclasses of pui.BasicWidget. Before "setProperty" is called, pui.BasicWidget does some internal work with the property information. Afterward, setProperty is called whenever Profound UI sets a property on a widget. The first time setProperty runs is during the "field type" setter, after the pui.BasicWidget is constructed. The setProperty function accepts one parameter, an object that contains information normally passed to property setters, including these options:
- propertyName - String. Name of the property being set; e.g. "field type", "id", "value"
- design - Boolean. True when the page is Visual/Node Designer
- properties - an object containing property names as keys and property values as values.
- value - String. Value being currently assigned to the property.
These properties of pui.BasicWidget can be accessed in sub-classes and externally.
- design - Boolean. True when the page is Visual or Node Designer.
- dom - Element. A reference to the main DIV element that contains the custom element's DOM sub-tree.
- widgetName - String. The unique name of the type of widget; e.g. existing widget names would be "grid", "chart", "icon", etc. The name is assigned by the constructor and is read-only.
Widget APIs Compatible with pui.BasicWidget
These widget APIs have been tested successfully or adapted to work with instances of or sub-classes of pui.BasicWidget:
- applyProperty - This can be used for all properties. However, when applyProperty is passed the "field type" property on a pui.BasicWidget the widget gets destroyed and then constructed, losing existing property values. To refresh an instance of pui.BasicWidget call the public "render" method instead of re-setting "field type".
- changeElementValue / pui.set - for instances of and sub-classes of pui.BasicWidget "changeElementValue" and "pui.set" simply call the "value" property setter; e.g. like applyProperty(..., "value", someValue);
- getElementValue / get - Calls the widget's "getValue" function to get a value and formats that value as a string according to the bound formatting information, if possible.
- getObj - returns the main DIV element containing the custom widget.
- hideElement - sets the "visibility" style of the widget's main DIV to "hidden".
- getInputFields - works as long as elements in the custom widget are not placed inside a Shadow DOM
- pui.click - works for input elements of type, "button", and button elements that have an onclick listener defined.
Below is an example of adding a widget and defining its behavior in a subclass of pui.BasicWidget (rather than in the "render" and "getValue" options supplied to pui.widgets.add).
With that code, the widget can be used in Visual Designer:
In runtime Profound UI automatically fetches the values stored in the custom widget, formats them, and submits them to the server. The picture below shows a color-widget with multiple bound values that were submitted to the server, and a ColorPicker in a subfile grid–demonstrating that the bound "color picker value" inside a subfile grid can be automatically handled.