cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Learn all about the Community Ranking System, a fun gamification element of the PTC Community. X

Create A Mashup Widget Extension Part 3

100% helpful (1/1)

 

 

Step 7: Widget Lifecycle at Runtime

 

When a Widget is first created, the runtime will obtain any declared Properties by calling the runtimeProperties() function.

 

  1. The property values that were saved in the Mashup definition will be loaded into your object without your code being called in any way.

  2. After the Widget is loaded but before it’s displayed on the screen, the runtime will call renderHtml() for you to return the HTML for your object. The runtime will render that HTML into the appropriate place in the DOM.

  3. Immediately after that HTML is added to the DOM, you will be called with afterRender(). This is the time to do the various jQuery bindings (if you need any). It is only at this point that you can reference the actual DOM elements, and you should only do this using code such as:

 

    // note that this is a jQuery object
    var widgetElement = this.domElement;

 

This is important because the runtime actually changes your DOM element ID (domElementId) and you should never rely on any ID other than the ID returned from this.

 

If you have defined an event that can be bound, whenever that event occurs, you should call the following:

 

    var widgetElement = this.domElement;
    // change ‘Clicked’ to be whatever your event name is that
    // you defined in your runtimeProperties that people bind to widgetElement.triggerHandler('Clicked');

4. If you have any properties bound as data targets, you will be called with updateProperty(). You are expected to update the DOM directly if the changed property affects the DOM - this is likely, otherwise why would the data be bound.

5. If you have properties that are defined as data sources and they are bound, you can be called with getProperty_{propertyName}() …. If you don’t define this function, the runtime will simply get the value from the property bag.

 

 

Step 8: 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 renderHtml().
  • this.jqElement - This is the jquery element.
  • this.getProperty(name) - Accessor.
  • this.setProperty(name,value) - Modifier.
  • this.updateSelection(propertyName, selectedRowIndices) - Call this anytime your Widget changes selected rows on data that is bound to a certain propertyName. For example, in a callback for an event like onSelectStateChanged(), you would call this API and the system will update any other Widgets relying on selected rows.

 

Step 9: Runtime Callbacks

 

The following functions on the widget are called by the runtime.

 

runtimeProperties() - [optional] Returns a JSON structure defining the properties of this widget. Optional properties are:

 

  • isContainer - true or false (default to false); Controls whether an instance of this widget can be a container for other widget instances.
  • needsDataLoadingAndError - true or false (defaults to false) - Set to true if you want your widget to display the standard 25% opacity when no data has been received and to turn red when there is an error retrieving data.
  • borderWidth - If your widget provides a border, set this to the width of the border. This helps ensure pixel-perfect WYSIWG between builder and runtime.
  • supportsAutoResize- If your widget supports auto-resize, set this to true.
  • propertyAttributes – If you have STRING properties that are localizable, list them here. For example, if TooltipLabel1 is localizable:

 

this.runtimeProperties = function () {
    return {
        'needsDataLoadingAndError': true,
        'propertyAttributes': {
            'TooltipLabel1': {'isLocalizable': true} 
        }
    }
};

 

renderHtml() [required] - Returns HTML fragment that runtime will place on the screen; the widget’s content container (e.g. div) must have a ‘widget- content’ class specified. After this container element is appended to the DOM, it becomes accessible via jqElement and its DOM element ID will be available in jqElementId.


afterRender() [optional] - Called after the widget HTML fragment is inserted into the DOM. Use this domElementId to find the DOM element ID. Use this jqElement to use the jQuery reference to this DOM element.


beforeDestroy() [optional but highly recommended] - This is called anytime the widget is unloaded. This is where to:

 

  • unbind any bindings
  • clear any data set with .data()
  • destroy any third-party libraries or plugins, call their destructors, etc.
  • free any memory you allocated or are holding onto in closures by setting the variables to null
    There is no need to destroy the DOM elements inside the widget, they will be destroyed for you by the runtime.

resize(width,height) [optional – Only useful if you declare supportsAutoResize: true] - This is called anytime the widget is resized. Some widgets don’t need to handle this, for example, if the widget’s elements and CSS auto-scale. But others (most widgets) need to actually do something to accommodate the widget changing size.


handleSelectionUpdate(propertyName, selectedRows, selectedRowIndices) - Called whenever selectedRows has been modified by the data source you’re bound to on that PropertyName. selectedRows is an array of the actual data and selectedRowIndices is an array of the indices of the selected rows. Note: To get the full selectedRows event functionality without having to bind a list or grid widget, this function must be defined.

 

serviceInvoked(serviceName)- serviceInvoked() - Called whenever a service you defined is triggered.


updateProperty(updatePropertyInfo) - updatePropertyInfo 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 widget’s updateProperty() will be called every time the source data is changed. You need to check updatePropertyInfo. TargetProperty to determine what aspect of the widget needs to be updated. An example from thingworx.widget.image.js:

 

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);
       }
    }
};

 

NOTE: In the code above, we set a local copy of the property in our widget object, so if that property is bound as a data source for a parameter to a service call (or any other binding) - the runtime system can simply get the property from the property bag. Alternately, we could supply a custom getProperty_ {propertyName} method and store the value some other way.

 

getProperty_{propertyName}() - Anytime that the runtime needs a property value, it checks to see if the widget implements a function that overrides and gets the value of that property. This is used when the runtime is pulling data from the widget to populate parameters for a service call.

 

 

Click here to view Part 4 of this guide.

Version history
Last update:
‎Feb 23, 2023 09:07 AM
Updated by:
Labels (1)
Tags (1)