Creating JavaScript Form Controls
  • 12 Aug 2022
  • 6 Minutes to read
  • Dark
    Light

Creating JavaScript Form Controls

  • Dark
    Light

Article Summary

Browser Support
Decisions supports a wide range of web browsers.  For ideal user experience, avoid using incompatible JS syntax. For more information on browser compatibility, see Decisions Browser Compatibility.

Users may build their own custom Form controls with JavaScript (JS) to use within the platform. Similar to built-in controls, JS controls also contain inputs and outputs.

The process for configuring each of these JS controls is primarily the same. For Action, Data, and Page controls, a JS file will need to be uploaded and have its Class name declared in Decisions. 

Scripts and Style JS controls only need to have the JS files uploaded. Below is a brief explanation of the different control types.

Control TypeFunction
Action ControlAction Controls are Form Controls to trigger actions, i.e., Button, Link.
Data ControlThis is a Form Control that allows users to work with Data like JS Data Grids or Text Boxes.
Page ControlThese are Page Controls, custom JS components used in the Dashboard/Page Designer.
ScriptsThis feature allows users to include Custom Scripts to upload JS Controls
StylesThis feature allows users to include Custom Styles (CSS) to upload JS Controls.


Troubleshooting JS Controls

To troubleshoot JS controls, chrome developer tools will need to be used.

This can be accessed by pressing F12 on the keyboard and navigating to the 'Network' tab to verify the JS control is running. Another troubleshooting step would be to empty the cache and reload it to ensure the cache is empty.

Creating the Control

This example was used for instructional purposes. Developers can write any type of example that is logical and applicable for business-specific use cases.

This example details how to create a custom Data Control. It will consist of a single Button, and the control output will be the number of times the button has been clicked. The control won't need any input data.
All JavaScript data controls will have these 4 specific functions:

 interface JSBasedComponentInterface {
    initialize(host: JQuery, component: any): void;
    resize(height: number, width: number): void;
    setValue?(data: any): void;
    getValue?(): any;
  }


FunctionsPurpose
initializeThis function will be called one time when the control is being created.
resizeThis function can handle special resizing rules, but most controls won't need to modify it - copying & pasting this 'resize' function should suffice when necessary.
setValueThis function is used when control takes input data.
For an example that includes input data, see the Creating JavaScript Controls (Advanced) for this feature.
getValueThis is where the output will be returned.


The completed JavaScript control for this example will look like the code block below. Save this as MyControl.js, and then load it into Decisions.

 function MyControl() { };

 MyControl.prototype.initialize = function(host, component){
  // Here we assign 'host' to a variable on this control,
    //   so that we can access it later:
  this.host = host;
  // Our counter starts at 0:
  this.timesClicked = 0;

  // Create and configure the button:
  var button = document.createElement('button');
  button.type = 'button';
  button.textContent = 'Click me';

  var thisControl = this; // To avoid 'this' problems inside the onclick event.

  // When the button is clicked, increment our counter:
  button.onclick = function(e){
   thisControl.timesClicked++;
  };

  // Add the button to the 'host' jquery object:
  host.append(button);
 };

 MyControl.prototype.resize = function(height, width) {
  if (this.host && height && width && (height > 0) && (width > 0)) {
   this.host.css({ width: width, height: height });
  }
 };

 MyControl.prototype.setValue = function(data){
  // This control has no inputs, so no code is necessary here.
 };

 MyControl.prototype.getValue = function() {
  // Output data should be an object with properties that match the
    //   names of our outputs. In this case, our output is named 'TimesClicked'.
  return {
   TimesClicked: this.timesClicked
  };
 };

Loading a .js file into Decisions as a JS form control

  1. Navigate to a Designer Folder. Select CREATE FORM.
  2. In the Create Form dialog, choose the JavaScript Control menu and Add Data Control.
  3. In the Add Javascript Control window, name the control. This control has no input data; nothing needs to be added to the Input Data section.
  4. Select the Different Output Data checkbox; the Output Data section will appear.
  5. Select Add New under the Output Data section. The control has a numerical output named "TimesClicked". In the Name field, type "TimesClicked", and pick Int32 [Number] for the Type field, then select 'Ok'.
  6. In the Runtime Information section, the JS Class Name must match the class name inside the .js file. The class name is 'MyControl'; type MyControl in the JS Class Name field. Select Choose File to upload the MyJsControl.js file.
    JS Class Name Must Match
    Under the 'Runtime Information', the 'JS Class Name' must match the class name in the JavaScript file. If they do not match, the JS control will not function in the form. 
  7. Select SAVE CONTROL to create the new Form Control.

Using a JS control in a Form

  1. Create a new Form
  2. In the Toolbox panel, drag a Button onto the Form. Name it 'Submit'.
  3. Expand JS Controls >[Current Folder] drag the JS Control to the form. Save and close the Form Designer.
  4. Create a Flow to display the form. Add a Show Form step, and select the Form that was just created. Select Debug in the top action panel. 
  5. Select the 'Click me' button multiple times, then select Submit.
  6. Select the Show Form step, and then select View Output Data. Notice that the output from the Form includes the TimesClicked.

Creating An Action Control

This example will demonstrate a JS Action Control. The following JavaScript code and the file it is located in will be used for illustration.

 

  function ListButtonControl() { };

  ListButtonControl.prototype.initialize = function(host, component) {
    // Keep track of the host; we'll need it later.
    this.host = host;
    // Initialize our count data:
    this.currentCount = 0;
    this.totalCount = 0;
    // This one is important when we have input data. See 'consumeData' for details.
    this.lastConsumed = null;

    // We're going to put both buttons in a div, then append the div to the host:
    var control = document.createElement('div');

	// Loop through all possible outcome names.
	for (var outcome of component.PossibleOutcomeNames) {
		// create button element
		var button = document.createElement('button');
		// add class
		button.classList.add('myControlButton');
		button.type = 'button';
		// set the text same as outcome name
		button.textContent = outcome;

		var thisControl = this; // To avoid 'this' problems inside the onclick event.

		button.onclick = function(e){
			// to submit the form when button is clicked, selectPath should be called with correct outcome name 
			// the outcome here should be from possibleOutcome names that we define while creating the JS action control
			// otherwise the flow will throw an error.
			component.selectPath(this.textContent);
		};

		control.appendChild(button);
	}
	
    host.append(control);

    // The two buttons appear too close together unless we add some css:
    var style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = '.myControlButton{ margin: 5px; height: 30px; color: #fff;background-color: #007bff;border-color: #007bff;border: 1px solid transparent;padding: .375rem .75rem;font-size: 1rem;line-height: 1.5; }';
    document.head.appendChild(style);
  };
  
  ListButtonControl.prototype.resize = function(height, width) {
    if (this.host && height && width && (height > 0) && (width > 0)) {
      this.host.css({ width: width, height: height });
    }
  };


  1. Navigate to a Designer Folder. Select CREATE FORM.
  2. In the Create Form dialog, choose the JavaScript Control menu and Add Action Control.
  3. In the Add Javascript Control window, name the control. This control has no input data; nothing needs to be added to the Input Data section.
  4. Set Possible Outcome Paths to: 'Submit', 'Cancel', and 'Reset'
  5. Declare the JS Class name to "ListButtonControl"
  6. Navigate to the previously created Form.
  7. In the Toolbox panel, expand JS Controls >[Current Folder] and drag the ListButtonControl to the form. 
  8. Save and close the Form Designer.
  9. Debug the Flow. Notice that the JS Action Control Button list behaves like a normal button in Decisions. Depending on the button clicked, the Flow will take that outcome path.

Was this article helpful?