Ir para o conteúdo

Widgets

Overview

Widgets in Vinyl allow developers to provide 3rd party (or their own) code in order to show a customized Control on the page. Widgets allow you to define more metadata, see the Archive File Contents section for detail. Parameters now support a more robust definition, see the Widget API section for detail.

See the Widget Download Library for a list of supported Widgets you can use in Vinyl.

widgetimage.png

Note

Vinyl supports keyboard shortcuts, which in edge case scenarios may interfere with widgets. If you encounter issues with your widget, please review the Troubleshooting section below.

Widget Guidelines

  1. Widgets should show the underlying value, or it should be obvious what the underlying value is.

    • Good: Value displayed

      Image 2016 4 4 16 0 17

    • Good: Value obvious

      Image 2016 4 4 16 2 48

    • Bad:

      Image 2016 4 4 16 1 6

  2. Widget Testing. Remember to consider how the widget will be interacted with on touch and non-touch devices.

  3. Widgets should respect auto-edit and auto-save. Widgets will get this behavior from Vinyl automatically.

Archive File Contents

_manifest.json

All widgets include a manifest file. New in Vinyl 3.2 you can define more metadata in this file, as described below.

manifest.json
{
    "name": "Slider", 
    "developer": "Vinyl",
    "binder": "binder.js", 
    "template": "view.html",
    ...
    "targetContainer": false,
    "purpose": "Site",
    "parameters": [
        {
            "name": "Parameter name",
            "default": "default value",
            "translate": true
        }
    ] 
}
  • name: The name of the Widget that will appear in the Vinyl IDE as well as become the archive file name.

  • developer: The username of the developer working on this Widget.

  • binder: The filename of the Widget binder. See below for more information.

  • template: The filename of the template HTML file. See below for more information.

  • targetContainer: Supports the value true or false.

  • purpose: Supports the defined value of Site or Field, which indicates how the Widget is intended to be used.

  • parameters: Supports an array of parameters metadata, for each:

    • name: the parameter name
    • default: a string containing the default value
    • translate: supports the value true or false
  • version: Version number of the Widget. Increment this number to ensure users receive the latest edition of your code.

  • createdOn: Date this version was released. Informational purposes only.

  • dependencies: Comma delimited list of any dependencies required by your Widget binder. The order these files appear will match the order they will appear in the dependency array of the Widget API. Be sure to include the file extension.

    • JavaScript
    • CSS

    For example, if you define a library that returns a reference you need to use to install onto an element:

    Manifest Entry
    "javascript": [
      "noUiSlider.8.0.2/nouislider.js",
      "noUiSlider.8.0.2/nouislider_extras.js"
    ]
    

    Your Widget API context would include both of those objects:

    Usage
    var install = function (holderElement, context) {
      var sliderLibrary = context.loadedDependencies[0];
      sliderLibrary.createSlider(holderElement);
    }
    

    Note

    Even if you have no dependencies, include the JavaScript and CSS properties with an empty array.

    Manifest Entry
    "javascript": [],
    "css": []
    

binder.js

binder.js

define(function () {
    return {
        callbacks: {
            events: {
                install: function (holderElement, context) {},
                uninstall: function (holderElement, context) {}
            }
        }
    };
});

The binder provides two callbacks required to bind the Vinyl API to your libraries. In each, two function parameters are provided.

  • holderElement: A DOM element that contains the HTML mark-up provided in the specified template file. As this file is optional, the holder element may be empty. The holder element is the cell the Widget will be implementing. It is the area highlighted in the screenshot below and does not include the field's label.

    Image 2015 10 2 13 14 57

  • context: An instance of the Widget API context. This object contains any JavaScript depencencies specified in the binder as well as access to the data in the cell and panel.

  • view.html (optional): This file contains all static HTML required to load this Widget. If not specified, the Widget will be created without any content and the install callback defined in the binder will need to render any HTML required.

Widget API

getCell()
Returns an instance of the WidgetApiCell.

getRow()
Returns an instance of the WidgetApiRow.

isEditState() - boolean
Identifies if the row is editable.

getParameter(name) - string
Will retrieve the defined parameter from either the default value or the cell in this row that was named by the designer.

loadedDependencies
A property containing an array of objects returned by RequireJS. This array is provided in the same order as the dependencies are defined in the _manifest.json file.

WidgetApiCell
Represents a single cell. Cells are the backing view model of the control seen on the page. They contain values, can be monitored for changes, and exist in a row of a table.

value - string
This property can be used to get and set the underlying value of the cell.

Usage
customTextbox.on('change', function (value) {
    cell.value = value;
});

formattedValue - string
This property can be used to get and set the underlying display value of the cell. For example, a percent field's underlying value would be 0.25, while the display value (formatted value) is "25%". Or, a list control could have a value of a GUID, while the formatted value is the first and last name of a client.

persistedValue - string
This property can be used to get the underlying persisted value of the cell. A persisted value is the un-edited value currently stored in the data source. This can be used to revert a cell to a clean state.

setDataChangeCallback
This function is used to set callbacks to run when the form the widget is on gets new data.

Usage
context.setDataChangeCallback(function () {
   var updatedMin = parseInt(context.getParameter("Min"), 10);
});

setChangeCallback(name: string, value: Function)
This function is used to set callbacks on a cell. The following named call backs can be defined:

  • value
  • formattedValue
  • disabled
Usage
cell.setChangeCallback('value', function (value) {
    console.log("The cell's value has been changed to", value);
});

Vinyl may cause changes to the cell during validation events, if default values are set or if another Widget causes changes that affect this cell. Vinyl may also disable cells when events are being executed.

Vinyl will pass in a single parameter to the provided callback containing the changed value. In the case of disabled, the value is either true or false.

dropChangeCallback(name: string)
Removes the subscription to a change callback.

WidgetApiRow
Represents a row in the data source. This row contains the cell that the Widget is implementing.

getCellByColumnName(name: string) - WidgetApiCell
Returns an instance of a cell in this row. Name is case sensitive and must match the name as defined on the control, not the data source name.

edit()
Changes the row into edit mode.

save()
Saves any modified values back onto the data source.

deleteRow()
Will attempt to delete the row from the data source.

Parameters
Parameters for a widget can be defined at the panel level. When adding a parameter, the developer can configure:

  • Widget Parameter: Name assigned to the parameter value.
  • Parameter Type: Defaults to Control, can also be defined as Column or Static Value. Depending on which Type you define, you will have different values to configure accordingly:

    • Control:
      • Target Control: A control from the parent panel that will provide with this parameter value.
      • Use Formatted Value: Use the formatted display value.
      • Active: Indicates if this binding is active or not. Inactive bindings won't be used.
    • Column:
      • Target Column: A column from the parent panel's source table that will provide with this parameter value.
      • Use Formatted Value: Use the formatted display value.
      • Active: Indicates if this binding is active or not. Inactive bindings won't be used.
    • Static Value:
      • Value: Static value for the parameter.
      • Translatable: If enabled, allows the Widget to be translated where applicable.
      • Active: Indicates if this binding is active or not. Inactive bindings won't be used.

How to Build a Widget & Troubleshooting

Widgets are a blank slate. Vinyl will run the widget code instead of Vinyl's implementation.

Showing the current value
If you are rendering a thermometer, for example, you'll likely need to include the current value along with the mercury level. (see $3,500 example text below)

However, a star rating widget may not need to indicate the actual cell value.

Image 2016 4 4 10 35 6

Getting and setting the value from Vinyl onto your widget
Vinyl can update the value via defaults or changes to parent records. Your library will need to be able to update itself when these events happen.

Providing callbacks allows Vinyl to run your code when it needs to send new values to your widget. See setChangeCallback above.

Also, when installing a library you will typically need to set the initial value from the cell provided. Vinyl will not run the Change Callback on install, only when events require it.

Uploading new versions & debugging
Once you have a widget operational and you are debugging an error, follow the following steps:

  1. Zip the contents of the local folder you're working on (make sure you do not zip the parent folder itself, this will create an extra folder in the zip file)
  2. Upload to the widget zip file in the Look & Feel application
  3. Press refresh on the page using your widget. Note: you may need to disable your browser cache while developing, otherwise you could end up with stale code.

View vs. Edit state
When adding a widget to a panel, you can specify if your widget will handle the rendering of both edit and view state. If your widget only handles edit state, Vinyl will render the cell value when in view state.

If your widget handles both states, your control CAN be used to edit values without needing to click the edit toolbar button first.

To do this, you need to switch the row to edit state if it's not already. Here is an example:

Usage
if (!context.isEditState()) {
  context.getRow().edit();
}
context.getCell().value = myNewValueVariable;
context.getRow().save();

You could also use the isEditState property to render a "read-only" version of the widget that displays the value but can't be used to modify the cell.

Loading large dependencies
Large resources like JQuery UI take a long time to download and install. For performance purposes, it is recommended that only light libraries or libraries that use existing Vinyl dependencies are implemented. Some errors have been reported when dependencies load too slowly.

Working with binary data
Some cells in Vinyl can contain binary data stored as a base64 string. Libraries can be used to modify and store data in these cells, such as image editing utilities. See the Image Resizer library in the Vinyl collection for example code.

row.ViewModel
The current version of Vinyl exposes a parameter called ViewModel in the row API. This provides access to the Vinyl back-end data and will not be guaranteed to work when upgrading Vinyl. It is not recommended to write code that relies on this property.

Site Widgets

Widgets can also be "site level". This is defined at the widget level and they are used via Control Center > Instance Settings > Site Widgets.

Site widgets are run as soon as the browser loads. This allows code to execute as soon as possible. The code will run async, meaning the page won't wait to render itself until the code runs.

Site parameters are not data bound, they support plain text values only.

How to add a Site Widget in Vinyl

  1. Go to the App Workbench > Look & Feel > Widgets
  2. Select the Collection you want to add the Widget to
  3. Click the + Widget button
  4. Provide a Name for the Widget. For example: Dial Widget
  5. Click Browse and locate the Widget .zip file containing all required Widget files, select it and click Open
  6. Provide any Documentation to describe the widget. Help text information appearing in the IDE for a widget is provided by the widget record.
  7. Click Save
  8. On the Widget Parameters panel, click + Parameter and define any required Parameters for the Widget
  9. On the page that will run your Widget, select the Widget from the Widget Information region of the Control Designer and set the Interface and Active Mode values

API

getParameter(name) - string
Will retreive the defined parameter from either the default value or the parameter provided by the designer via the Site Widget definition.

getCurrentPageLocation() - string
Gets the current URL of the page.

getCurrentAuthenticationUserName() - string
Gets the currently logged in username, or null if not authenticated.

onPageLocationChange(handler: Function(event))
This function is used to set callbacks that run when the page location changes. Will return the path as a string.

Note

Does not run for the first page location when the site widget is installed. Access the getCurrentPageLocation() once to get the first address.

Use offPageLocationChange(handler) to uninstall this listener.

onAuthenticationChange(handler: Function(event))
This function is used to set callbacks that run when the authenticated user changes. Will return the username as a string.

Note

Does not run for the logged in user when the site widget is installed. Access the getCurrentAuthenticationUserName() once to get the first address.

Use offAuthenticationChange(handler) to uninstall this listener.

Troubleshooting

Vinyl supports keyboard shortcuts, which some widget libraries may confict with.Vinyl currently supports the following hotkeys: text; enter; esc; left-arrow; up-arrow; right-arrow; down-arrow; backtick; and delete.

The following instructions allow you to disable hotkey support to a given HTML element and its child elements.

To ignore all keyboard shortcuts either use a CSS class or the data field value vinyl-hotkeys-ignore:

  • <div class="vinyl-hotkeys-ignore"></div>
  • <div data-vinyl-hotkeys-ignore="true"></div>

To ignore just some keyboard bindings, add them to the CSS class suffix. If there's more than one word, hyphenate them in the CSS class suffix:

  • <div class="vinyl-hotkeys-ignore-text"></div>
  • <div data-vinyl-hotkeys-ignore-text="true"></div>
  • <div class="vinyl-hotkeys-ignore-left-allow"></div>
  • <div data-vinyl-hotkeys-ignore-left-allow="true"></div>

Vinyl will automitically ignore text fields and divs marked as content editable:

  • <div contenteditable="true"></div>