Chapter 4—JSON Components

You can define your own remote form controls using JSON and JavaScript, and use them on JavaScript Remote forms in your web and mobile applications. Using the same technique, you can wrap ready-made JavaScript components, available from any third-party, opening up endless possibilities for new controls to use in your web and mobile apps.

This method of creating JavaScript components provides an alternative to creating external components using C++ and our JavaScript SDK, which is the current method used for creating JavaScript external components. It also means you only need to understand JSON and JavaScript, together with our JavaScript interfaces on the client, in order to create and use JSON defined JavaScript controls, either in your own web or mobile apps, or to provide to the wider Omnis community. There are a number of JSON components on our GitHub site: https://github.com/OmnisStudio, for example, Omnis-Signature (for signing documents) and Omnis-FiveStars (star rating component).

Having created a JSON defined component using the JSON Control Editor, the component will appear in the Component Store in the JSON Components group. You can drag the component onto your JavaScript remote form and set its properties using the Property Manager.

The design mode rendering of the JSON controls on a remote form is very basic, and does not reflect the actual control as it might appear on a remote form at runtime, although this is not a problem for some controls that do not require a visual interface.

JSON Control Editor

A JSON control is defined in a JSON file, called a JSON Control Definition (JCD) file, which you can create or edit using any text or JSON editor – if you are very familiar with JSON you may like to create the JCD using an editor. Alternatively, you can create the new JSON controls (create a JCD file) using a tool available under the Tools>>Add Ons menu, called the JSON Control Editor.

image1

The JSON Control Editor contains a template control that has all the necessary properties to create a basic JSON control. The editor allows you to set the properties for the control under each tab. To create a component, you edit the properties, click on Save, click on Build to build the control, and then click on Reload to load the component into the Component Store (the Build and Reload options will also prompt you to save if changes have been made). The New button removes any changes you have made to the default template and allows you to start again. In order to setup the properties and methods for your control you will need to refer to the JSON definitions later in this section.

Control Name

The name of the control must be unique, so you will need to change the Control Name in the editor (or just accept the default name if you are testing the editor). The default control name is prefixed with ‘net.omnis’ to show the preferred naming convention, but you should change this to your own company name, e.g. com.mycompany.mycontrol1, or use any appropriate naming convention. If you do use a dot in the control name, Omnis converts it to underscore, since dots cause an issue with the Omnis notation.

Control Properties

The following tabs are available to set the properties of the control:

The ‘Options’ item on the editor toolbar allows you to set custom JavaScript variable prefix for properties.

The Save option places the JSON control file in html/controls folder. The Build option places the JavaScript file for your control in the html/scripts folder in your development tree. It also prompts you to include a reference to the JavaScript file for the control in the jsctempl.htm file, which will ensure that the control is available for testing any remote forms that contain the new control. The Build option adds update markers and lets you update the JavaScript file if the markers already exist.

When you have built a JSON control you need to restart Omnis for it to load. After restarting Omnis, the control will appear under the JSON Components tab in the Component Store ready to use in your remote forms. When you deploy your app, you need to place the JSON and JavaScript files in the corresponding folders in your Web Server tree, and check that they are referenced in the html page containing your remote form.

You could open the ‘control.json’ file created in the JSON Control Editor when you build the control from the template: this file will show you the typical structure of the JSON file required to define a new component.

Using Ready-made JS Components

When using ready-made JS components, that you have obtained from a third-party, you need to add the .js file(s) to the html/scripts folder in the Omnis tree, and any other CSS and image files required for the control need to be put in the appropriate folder(s). You will also need to add any properties, methods, and events in your JS control to the JSON definition file via the JSON Control Editor. There is a tech note on the Omnis website that describes the process of using a ready-made JS component in Omnis:

You will also need to refer to the JavaScript Control Reference in the JavaScript Component SDK docs which you can find here.

 

JSON Control Definition

This section describes the different properties that can be defined in the JCD file for the control and edited under the separate tabs in the JSON Control Editor (or when editing separate members using a text editor).

There is a new folder in the Omnis tree, html/controls, which contains a sub-folder for each JSON control you have defined. The names of these sub-folders are not critical, but it makes sense to use the same name as the control name.

The JSON Control Editor will create html/controls folder when you build your first control, otherwise if you are building your own controls you will need to create this folder (note this is not to be confused with the ‘htmlcontrols’ folder that contains controls that can be loaded in the oBrowser object).

There is a new external component named ‘jsControls’ in the jscomp folder, which handles all JSON defined controls. It loads and validates the controls at startup. All controls which pass validation are loaded into the new JSON Components group in the Component Store. If a control fails validation, jsControls opens the trace log, and adds a message to indicate there is a problem with the control. The exact problem can be found in a file called control_errors.txt in the control’s folder.

Each control must have a unique name. This is defined in control.json (see below), and you should use a convention similar to Java except that Omnis uses underscore rather than a dot, e.g. net_omnis_control1 could be the name of a control (using dots causes issues in the Omnis notation).

JSON Control Object

Each JSON control folder must contain a file named control.json containing a JSON object defining the control; the JSON file must be called control.json. The members of this object are defined in the following sections.

The control folder should also contain an image file which is used for the control icon in the Component Store, and when rendering the control on the remote form design window. This can be an SVG file (with the .svg extension) which can be themed. Alternatively, you can use PNG files (with the .png extension), but in this case, you need to provide all possible sizes including 16x16, 16x16_2x, 48x48 and 48x48_2x.

name

The name member is mandatory, and it specifies the name of the control; it becomes the external component control name. It is also used to create the JavaScript control class name, as ctrl_<name>. For example:

  "name": "net_omnis_control1"

In this case the JavaScript control class would be ctrl_net_omnis_control1.

flags

The flags member is mandatory. It is an object that allows certain features of the control to be configured. Each member of flags is optional, and defaults to false if it is omitted. Valid members are:

For example:

    "flags": {
        "beforeafterevents": true,
        "backcolorandalpha": true,
        "noenabled": true,
        "hasdefaultborder": false,
        "hasdisplayformat": true,
        "hasdragevents": true
    },

standardproperties

The standardproperties member is optional. It is an array of standard properties supported by the control; inclusion in the standardproperties member means the control will have the property. These are over and above the basic properties that apply to all controls e.g. active, name, etc.

Valid members of the standardproperties array are: “dataname", “effect", “bordercolor", “borderradius", “linestyle", “font", "textcolor", "align", “fontstyle", “fontsize", “horzscroll", “vertscroll", "autoscroll", “dragmode”.

For example:

    "standardproperties": [
        "dataname",
        "effect",
        "bordercolor",
        "borderradius",
        "linestyle",
    ], 

properties

The properties member is mandatory. It is an object defining the control-specific properties of the control. Each member of the properties object is itself an object that contains members that describe the property. The name of each member of the properties object is the name of the control property, without the leading $. Valid members of each property object are:

For example:

     "properties": {
        "headercolor": {
            "id": 1,
            "desc": "The header color of the control",
            "type": "color",
            "tab": “appearance”,
            "initial": 255
        },
        "headericon": {
            "id": 2,
            "desc": "The header icon of the control",
            "popuptype": "icon",
            "tab": "appearance"
        },
        "rangeofexternalconstants": {
            "id": 3,
            "desc": "Range of external constants",
            "type": "integer",
            "extconstant": true,
            "constrangestart": "kNetOmnisControl1Range1",
            "constrangeend": "kNetOmnisControl1Range3",
        }
    }

multivalueproperties

The multivalueproperties member is optional. It allows you to set up a control to have multiple values for certain properties. It is an object with members as follows:

For example:

     "multivalueproperties": {
        "currentitemproperty": "curitem",
        "itemlistproperty": "itemlist",
        "moveitemproperty": "move",
        "itemcountproperty": "itemcount",
        "properties": {
            "mvprop1": 1,
            "mvprop2": 2
            }
        }
    } 

constants

The constants member is mandatory. It is an object defining the constants for the control. Each member of the constants object is itself an object that contains members that describe the constant. The name of each member of the constants object is the name of the constant. Valid members of each constant object are:

For example:

    "constants": {
        "kNetOmnisControlHeaderColor": {
            "value": 123,
            "desc": "The description of this constant"
        },
        "kNetOmnisControl1Range1": {
            "value": 3,
            "desc": "Range constant 1”,
               “group": “Ranges"
        },
        "kNetOmnisControl1Range2": {
            "value": 5,
            "desc": "Range constant 2"
        }
    }

events

The events member is optional. It specifies the events that the control generates (in addition to those specified by the flags member, i.e. before, after, and drag events). Each member of the events object identifies an event. The name of each member is the name of the event, including the “ev” prefix. Certain standard events can be specified: evClick, evDoubleClick, evTabSelected, evCellChanges, evHeaderClick and evHeadedListDisplayOrderChanged. Valid members of each event object are:

For example:

   "events": {
        "evNetOmnisControlOpened": {
            "id": 1,
            "desc": "The event sent when the control opens",
            "parameters": [
                {
                    "name": "name",
                    "type": "character",
                    "desc": "The name event parameter"
                },
                {
                    "name": "name2",
                    "type": "integer",
                    "desc": "The second event parameter"
                }
            ]
        },
        "evClick": {
            "parameters": [
                {
                    "name": "zname1",
                    "type": "character",
                    "desc": "The zname1 event parameter"
                },
                {
                    "name": "zname2",
                    "type": "integer",
                    "desc": "The zname2 event parameter"
                },
                {
                    "name": "horzcell",
                    "type": "character",
                    "desc": "the horz cell event parameter"
                }
            ]
        } 

methods

The methods member is optional. It specifies the client-executed methods that the control provides. Each member of the methods object identifies a method. The name of each member is the name of the method, including the “$” prefix. Valid members of each method object are:

For example:

    "methods": {
        "$mymethod1": {
            "id": 1,
            "desc": "This is my method",
            "type": "integer",
            "parameters": [
                {
                    "name": "p1",
                    "type": "character",
                    "altered": true,
                    "desc": "The parameter p1"
                },
                {
                    "name": "p2",
                    "type": "integer",
                    "desc": "The parameter p2",
                    "optional":true
                }
            ]
        }
    }

html

The html member is mandatory. It specifies how the initial HTML sent to the client for the control is generated. It is an object with members as follows:

For example:

    "html": {
        "template": "<div %o %s data-props='%p' data-mvprops='%m'></div>",
        "extrastyles":"margin:1px;"
    }

The resulting inner div for the control looks like this:

<div style='position:absolute; top:0px; left:0px; height:106px; width:88px; font- family:'Times New Roman',Georgia,Serif; font-size:12pt;font-weight:bold; font- style:italic;text-align:right;color:#00FFFF; overflow-x:auto; overflow-y:auto;margin:1px;'data-backgroundcolor='#555555; rgba(85,85,85,1.0000)' data-dragmode='1' data- effect='1' data-linestyle='1' data-bordercolor='16711935' data-props='{"headercolor":"#FF0000","headericon":"icons/datafile/omnispic/001663n16.png? 46", "rangeofinternalconstants":14, "rangeofexternalconstants":5, "headerpattern": 1, "headerfontstyle":4, "headerlinestyle":7, "headermultiline":"Lots of text entered like this\rwith multiple\rlines\r", "headerset": 13, "headerremotemenu":"NewRemoteMenu", "headerfont":"Courier New,Monospace"}' data- mvprops='[{"mvprop1":1,"mvprop2":false,"mvprop3":""}, {"mvprop1": 2,"mvprop2":true, "mvprop3":"NewRemoteMenu"}, {"mvprop1": 2,"mvprop2":true,"mvprop3":"aaaa"}]'></div>

Note that it is important to use single quotes around the attributes in the template, since JSON includes double quotes. jsControls escapes any single quotes in the JSON it inserts into the place-holders as \u0027.

customtabname

The customtabname member is optional. If specified, it is the name of the custom properties tab for the control shown in the Property Manager.

JavaScript

When you have created a JSON control and added it to your Omnis tree, you can add the supporting JavaScript file to the remote form template in the HTML folder (the JSON Control Editor will do this automatically). To do this, you can add:

    <script type="text/javascript" src="scripts/ctl_net_omnis_mycontrol.js"></script>

to the scripts section of the jsctempl.htm file (in the html folder) so the control is always included in the test HTML page for your remote form; it also needs to be included in the HTML page serving your deployed web or mobile app.