Table Of Contents

Creating a Custom Widget to Add to a Dashboard

Last Modified: November 7, 2019

Write and import a JavaScript wrapper to enable SystemLink Server to call and support custom widgets in a free-form dashboard.

For SystemLink to support a custom widget, the widget needs to have a JavaScript wrapper. A JavaScript wrapper is an ES5 class, which contains functions that perform operations, such as making the widget's properties appear in the configuration pane of Dashboards, adding the widget to the palette, and creating the widget when you add it to the panel.

What to Use

  • External JavaScript file
  • Dashboards

What to Do

  1. Create wrapper code for your custom widget in an external JavaScript file.

    The following code is an example of what a JavaScript wrapper may look like for a custom widget. It wraps a spectrum color picker, which Dashboards already uses as the color picker in the configuration pane.

    Customize the following code for your unique programming goals.

    var TestScope = {}
    /*1*/
    (function () {
        'use strict'; /*2*/
        TestScope.ColorBoxViewModel = class ColorBoxViewModel extends PexpipeScope.ViewModels.BaseViewModel {
            constructor () {
                super();
                this._jqId = '';
            }
    
            /*3*/
            createView (jqParent) {
                var div = document.createElement('div');
                div.style.position = 'absolute';
                var input = document.createElement('input');
                input.type = 'text';
                input.id = this.getId() ;
                $(div).append(input);
                jqParent.append(div);
                $('#' + this.getId()).css({width: '100%', height: '100%'});
                $('#' + this.getId()).spectrum({
                    preferredFormat: 'hex',
                    showInput: true,
                    showAlpha: true
                });
                $('#' + this.getId()).spectrum('set', '#000000');
                $(div).children('.sp-replacer').css('padding', '0px');
                this.setView($(div));
                this.refreshView();
            }
    
            removeView () {
                $(this.getView()).remove();
            }
    
            /*4*/ 
            getIsInput () {
                return true;
            }
    
            /*5*/ 
            refreshView () {
                var model = this._model;
                this.getView().css('left', model.getX() + this.getUnits());
                this.getView().css('top', model.getY() + this.getUnits());
                this.getView().width(model.getWidth() + this.getUnits());
                this.getView().height(model.getHeight() + this.getUnits());
                this.getView().children('.sp-replacer').width(model.getWidth() + this.getUnits());
                this.getView().children('.sp-replacer').height(model.getHeight() + this.getUnits());
            }
    
            /*6*/ 
            addEventHandler (callback) {
                var that = this;
                $('#' + this.getId()).change(function () {
                    if (callback !== undefined) {
                        var color = $('#' + that.getId()).val();
                        callback(color);
                    }
                });
            }
    
            /*7*/
            getDefaultAttributeValue (name) {
                var value;
                // var element = this.getView();
                switch (name) {
                    case 'value':
                        value = 'rgb(255,255,255)';
                        break;
                    default:
                        value = PexpipeScope.ViewModels.BaseViewModel.prototype.getDefaultAttributeValue.call(this, name);
                        break;
                }
    
                return value;
            }
    
            /*8*/  
            setAttributeValue (name, value) {
                if (value !== undefined) {
                    switch (name) {
                        case 'value':
                            if (typeof value === 'string' && value !== '') {
                                $('#' + this.getId()).spectrum('set', value);
                            }
                            break;
                        default:
                            PexpipeScope.ViewModels.BaseViewModel.prototype.setAttributeValue.call(this, name, value);
                            break;
                    }
                }
            }
    
            /*9*/
            getPaletteEntry () {
                return {
                    name: "Color box input", toolTip: "Color input control",
                        WidgetTemplate: { type: "spectrum", width: "30px", height: "30px", prefix: "spectrum" }
                }
            }
    
            /*10*/
            getWidgetPropertyDefn () {
                return { type: 'spectrum', definitions: [
                    // one entry per property group
                    {
                        name: '',
                        propertyGroup: [
                            // one entry per property
                            {propertyDefinition: {name: 'value', label: 'Value', type: 'color'}},
                        ]
                    }
                ]
                }
            }
        }
    }());
    (function () { 
    } ());

    Wraps the contents of the entire wrapper JavaScript file in an immediately invoked function expression (IIFE). The IIFE creates a new lexical scope which prevents you from unintentionally adding objects to the global scope.

    'use strict';

    Configures the IIFE to use JavaScript strict mode. Strict mode improves error handling and allows browsers to make certain optimizations.

    createView (jqParent)

    Creates an instance of the custom control you want to import to the dashboard and append it to the jQuery parent.

    getIsInput

    Enables the user to write values if the custom control is an input control and then returns the values.

    refreshView

    Refreshes the position and size of the control based on user dashboard actions with the custom item control.

    addEventHandler (callback)

    Adds an event handler to the control, if it's an input. Then it calls the callback function when the input completes.

    getDefaultAttributeValue (name)

    Returns the default value for each named property. The script calls this function when the user selects the control but did not specify a value in the paletteEntry.

    setAttributeValue (name, value)

    Changes the value of the named property you specify. The script calls this function when the user changes the value from the property editor pane or a bound tag.

    getPaletteEntry

    Returns a JavaScript object representing the palette entry.

    getWidgetPropertyDefn

    Returns the JavaScript object representing the list of properties in the configuration pane and properties with tags bindings.

  2. When you finish creating your JavaScript wrapper, upload the file onto a server and copy its URL.
  3. In NI SystemLink Web Application, click Dashboards.
  4. Open the dashboard you want to add the custom widget to and open it.
  5. Click »Edit.
  6. Select Utilities»Custom widget»Import....
  7. Complete the following steps to import the custom widget.
    1. Under Scripts, click + to add the URL of your hosted JavaScript wrapper. Click OK.
    2. Enter a class name for the custom control and click OK.

      Your custom widget appears on the panel.

  8. Click Save and Play to view your dashboard.
  9. To edit or remove a custom widget, select Utilities»Custom widget»Import....

Recently Viewed Topics