Runtime Functions Available for Customizing ThingWorx Widgets
This section describes the functions available for widgets at runtime.
Widget Lifecycle in Runtime
• When a widget is first created, the runtime obtains any declared properties by calling the runtimeProperties() function.
• The property values that are saved in the mashup definition are loaded into your object without calling any function.
• After your widget is loaded but before it is rendered on to the screen, the runtime calls the function renderHtml(). In this function, you return the HTML for your object. The runtime renders the HTML returned by the function in the appropriate place in the DOM.
• After the HTML is added to the DOM, the function afterRender() is called. If required, you can perform jQuery bindings. At this point, you can reference the actual DOM elements. For example, use the following code to reference the DOM elements:
// note that this is a jQuery object
var widgetElement = this.domElement;
|
The runtime changes the ID of your DOM element. It is recommended to always use the jQuery object this.domElementId to get the ID of the DOM element.
|
• If you have defined an event that can be bound, you can trigger the event, as shown in the following example:
var widgetElement = this.domElement;
// change ‘Clicked’ to be your event name
// you defined in your runtimeProperties
widgetElement.triggerHandler('Clicked');
• If you have any properties bound as data targets, the function updateProperty() is called. You should update the DOM directly if the changed property affects the DOM. When the data is bound, in most cases the DOM changes.
• If you have properties that are defined as data sources and they are bound, you can call the function getProperty_{propertyName}(). If you do not define this function, the runtime gets the value from the property bag.
Runtime APIs Available to Widgets
The following APIs can be accessed by a widget in the context of the runtime:
• this.jqElementId—This is the DOM element ID of your object after the widget is rendered on the HTML page.
• this.jqElement—This is the jQuery element.
• this.getProperty(name)—Gets the name of the property.
• this.setProperty(name,value)—Sets the name and value of the property.
• this.updateSelection(propertyName,selectedRowIndices)—Call this function when your widget changes the property on the selected rows. These rows have data bound to it. For example, in a callback if you have defined an event such as onSelectStateChanged(), then call the API this.updateSelection(propertyName,selectedRowIndices) and the system updates all the widgets that are dependent on the selected rows.
Callbacks from Runtime to Your Widget
The following functions on the widget are called by the runtime:
• runtimeProperties() [optional]—Returns a JSON structure defining the properties of the widget.
Optional properties are:
Property
|
Description
|
isContainer
|
Specifies if an instance of the widget can be a container for other widget instances. The valid values are true and false. The default value of the property is fasle.
|
needsDataLoadingAndError
|
The valid values are true and false. The default value of the property is fasle. Set the property to true if you want the widget to display the standard 25% opacity when no data is received. The widget turns red when there is an error while retrieving the data.
|
borderWidth
|
If widget has a border, set this property to the width of the border. The property helps you ensure a pixel-perfect design during development and runtime.
|
supportsAutoResize
|
Specifies if the widget automatically supports resizing. The valid values are true and false.
|
propertyAttributes
|
If you have STRING properties that are localizable, list them in this property.
For example, if TooltipLabel1 is localizable:
this.runtimeProperties = function () { return { 'needsDataLoadingAndError': true, 'propertyAttributes': { 'TooltipLabel1': {'isLocalizable': true} } } };
|
• renderHtml() [required]—The function returns the HTML fragment that the runtime places on the screen. The content container of the widget, for example, div should have a widget-content class specified in it. After the class is specified, the container element is appended to the DOM. The container is accessible using jqElement and its DOM element ID is available in jqElementId.
• afterRender() [optional]—This function is called after the widget HTML fragment is inserted in the DOM. Use this.domElementId to get the DOM element ID. Use this.jqElement element to get the jQuery DOM element.
• beforeDestroy() [optional but highly recommended]—Call this function when the widget is removed from the screen. With this function, you can:
◦ Unbind any bindings
◦ Clear any data set with .data()
◦ Destroy any third-party libraries or plugins, call their destructors, and so on.
◦ Free any memory you allocated or are holding in closures, by setting all your variables to null
◦ You do not need to destroy the DOM elements inside the widget, they are destroyed by the runtime
◦ Destroy the DOM only by adding the DOMOnly argument to the function.
|
To use lazy loading with the widget, add the DOMOnly argument to the function.
|
• resize(width,height) [optional – Useful only if you declare supportsAutoResize: true]—This function is called when your widget is resized.
Some widgets do not need to handle this. For example, if the elements of the widget and CSS auto-scale.
However, most widgets require handling when the widget size changes.
• handleSelectionUpdate(propertyName, selectedRows, selectedRowIndices)—This function is called when the selected rows are modified by the data sources bound to it with the specified property. selectedRows is an array of the actual data, and selectedRowIndices is an array of the indices of the selected rows.
|
You must define this functionality to get the full selectedRows event functionality without having to bind a list or grid widget.
|
• serviceInvoked(serviceName)—The function is called when a service you defined is triggered.
• updateProperty(updatePropertyInfo)—updatePropertyInfo is an object with the following JSON structure:
{
DataShape: metadata for the rows returned
ActualDataRows: actual Data Rows
SourceProperty: SourceProperty
TargetProperty: TargetProperty
RawSinglePropertyValue: value of SourceProperty
in the first row of ActualDataRows
SinglePropertyValue: value of SourceProperty
in the first row of ActualDataRows
converted to the defined baseType of the
target property [not implemented yet],
SelectedRowIndices: an array of selected row indices
IsBoundToSelectedRows: a Boolean letting you know if this
is bound to SelectedRows
}
For each data binding, the updateProperty() of your widget is called every time the source data is changed. You should check updatePropertyInfo.TargetProperty to determine what aspect of your widget should be updated.
See the following example for a widget:
this.updateProperty = function (updatePropertyInfo) {
// get the img inside our widget in the DOM
var widgetElement = this.jqElement.find('img');
// if we're bound to a field in selected rows
// and there are no selected rows, we'd overwrite the
// default value if we didn't check here
if (updatePropertyInfo.RawSinglePropertyValue !==
undefined) {
// see which TargetProperty is updated
if (updatePropertyInfo.TargetProperty === 'sourceurl') {
// SourceUrl updated - update the <img src=
this.setProperty('sourceurl',
updatePropertyInfo.SinglePropertyValue);
widgetElement.attr("src",
updatePropertyInfo.SinglePropertyValue);
} else if (updatePropertyInfo.TargetProperty ===
'alternatetext') {
// AlternateText updated - update the <img alt=
this.setProperty('alternatetext',
updatePropertyInfo.SinglePropertyValue);
widgetElement.attr("alt",
updatePropertyInfo.SinglePropertyValue);
}
}
};
Set a local copy of the property in the widget object. This ensures that the runtime system can get the property from the property bag.
Alternatively, you can provide a custom getProperty_{propertyName} method and store the value in some other way.
• getProperty_{propertyName}()—When the runtime requires the property value, it checks to see if your widget implements a function to override and get the value of that property. This is used when the runtime is getting the data from your widget to populate parameters for a service call.