Dynamically adding COTG widgets

Capture OnTheGo (COTG) widgets can be added to a Form dynamically, via jQuery. For example: a new Camera element could be added when the user clicks an Add button. This topic explains how to implement this. It is assumed that you have a basic understanding of HTML forms, CSS, JavaScript, and jQuery.

Prerequisites

Before you can start writing code that adds a widget in response to an action of the user, you need the following:

  • Some element on the Form to trigger the creation of the widget. This could be anything that responds to an action of the user; a button or link, for example. Make sure that this element has an ID.

  • A Form element to which the new widget can be added; a <div> for example. Again, make sure to give this element an ID.

  • The HTML structure and attributes of the widget, so that you can recreate it in code. The ​HTML structure of a widget can be seen on the Source tab after inserting the same kind of widget into a Form in the Designer.

Also, if you don't have a JavaScript file for your code yet, add one to the resources of your template (see Adding JavaScript files to the Resources) and make sure to include that file in the Web context or in the Web section that contains the COTG Form (see Including a JavaScript file in a Web context).

Adding an event handler

First of all you need to write an event handler that responds to the event that is meant to trigger the creation of the widget (e.g. the onClick event of a button or link), by calling the function that creates the widget. The event handler has to be added on the $(document).ready() function, which is fired when the Form is loaded in the browser/app.

$(document).ready(function() {
$('#add-element').on('click', function() {
//call the function that creates the widget
});
});

Creating the widget

Now you can start writing the code that constructs, adds and initializes the widget. This code has to be based on jQuery.

Constructing the HTML

A widget basically is an HTML element with certain attributes and contents. The ​HTML structure of a widget can be seen on the Source tab after adding the widget to a Form in the Designer. In code, reconstruct the HTML. Make sure to give the new element an ID.

This code constructs the HTML of a Date element:

<label>date1
<input id="date1" role="cotg.DatePicker" readonly="" name="date1" type="text">
</label>

Adding it to the Form

Add the HTML to an element on the Form using the append() function.

The following code appends the contents of the variable html to an element on the Form that has the ID cameras:
$('#cameras').append(html);.

Initializing the widget

A widget has to be initialized to allow it to be actually used. Widgets that are already present in a Form at startup are initialized as soon as the Form is loaded in the app. A widget that has been added to a Form dynamically has to be initialized directly after adding it to the Form; otherwise the new widget won't respond to actions of the user, even though it is visible in the app.

Initializing a widget takes just one line of code, in which you select the new widget by its ID and call the initialization function on it. This code, for example, initializes a new Camera element that has the ID myCamera:

$(#myCamera).cotgPhotoWidget();

Optionally, while initializing an element, you can make settings for this specific element. These settings get prevalence over the options already specified in the HTML and over the default settings specified in the COTG plugin.

The code snippet below initializes a new Camera element (with the ID myCamera) with a number of settings:

$('#myCamera').cotgPhotoWidget({
quality: 50,
height: 1024,
width: 1024
});

The initialization functions and options of all widgets are listed in the Capture OnTheGo API: Capture OnTheGo API.

To learn how to set the defaults for one kind of elements, see Changing default settings for widgets.

Restoring a widget

When a Form is closed, the app stores the values of input fields to the local repository of the app, but the values of input fields of dynamically added widgets are not stored.
When you reopen the Form the original input fields and their values are restored. However, dynamically added widgets are not restored; this needs to be handled in code. How to do this is explained in another topic: Saving and restoring custom data and widgets.

Example: adding Camera widgets dynamically

The following code inserts a Camera widget when the user clicks on a link or button with the ID add-camera. The addCameraWidget() function creates and adds the widget. Each new widget gets the class camera-dyn. The number of input elements that have this class is used to construct a unique ID for each new Camera widget.
The HTML structure of the widget was copied from the Source tab after inserting a Camera widget to a Form in the user interface of the Designer. The addCameraWidget() function appends this HTML to a <div> with the ID cameras, which was already present in the form. Subsequently the widget is initialized so that it is linked to the COTG app and the hardware features of the device.

$(document).ready(function() {
$('#add-camera').on('click', function() {
var cameraID = "camera_" + getC​ameraIndex();
addCameraWidget(cameraID);
});
});

function getCameraIndex(){
return $("input.camera-dyn").length;
}

​function addCameraWidget(cameraID, value) {
if(typeof value == 'undefined') {
value = '';
}
var html = '<label>Camera' +
'<div id="' + cameraID + '" role="cotg.PhotoWidget">' +
'<div class="panel" role="control-wrapper" style="position:relative;">' +
'<img role="photo" src="">' +
'<input role="photo-data" class="camera-dyn" name="' + cameraID + '" type="hidden" value="' + value + '">' +
'</div>' +
'<button class="small" role="take-button" type="button">Take now</button>' +
'<button class="small" role="pick-button" type="button">Library</button>' +
'<button class="small" role="clear-button" type="button">Clear</button>' +
'</div></label>';
$('#cameras').append(html); // add the camera object to the DOM
$('#' + cameraID).cotgPhotoWidget(); // init COTG widget
}