Saving and restoring custom data and widgets
The Capture OnTheGo (COTG) app stores the values of the input fields to the local repository of the app upon closing the Form. On reopening the Form the original input fields and their values are restored. However, dynamically added widgets (see Dynamically adding COTG widgets) don't get restored. This needs to be handled in code. This topic explains how to do that.
Adding event listeners
In the process of closing and opening a Form two important events are triggered by the COTG library:
- olcotgsavestate. This event is meant for custom scripts to save information when the user closes or submits the Form. It occurs after the state of all static input fields has been saved.
- olcotgrestorestate. This event allows custom scripts to do something when the Form is reopened. It occurs after all static inputs have been restored.
To latch on to these events, you have to register a olcotgsavestate
listener and a olcotgrestorestate
listener, respectively, on the window
object. The window
object represents a window containing a DOM (document object model), in this case the COTG Form.
The function callback on its addEventListener
method allows you to implement custom code as part of the save and restore processes.
(For more information about the addEventListener
method see MDN Web Docs.)
The following code registers the olcotgsavestate
listener on the window
object.
window.addEventListener('olcotgsavestate', function(event) {
/* code to save custom data */
});
The following snippet does the same for the restore process.
window.addEventListener('olcotgrestorestate', function(event) {
/* code to retrieve custom data and restore custom widgets */
});
The following code combines the previously saved string with the restored URL of a (static) COTG Camera element:
window.addEventListener("olcotgrestorestate", function(event) {
var value = event.detail.state["myString"];
value = value + $("#camera1 img").attr("src");
$("form p").html(value);
};
Note: You should not register for these events after the document has loaded (e.g. on the $(document).ready()
event), because these events might get triggered before the document is ready.
Place your code in a separate JavaScript file 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). For this file, the order in which JavaScript files are included in the template doesn't matter.
Handling the save and restore events
The code inside the function callback of the added event listeners should respond to the event, by saving or retrieving custom information, respectively.
When the COTG app saves the Form, you can store extra information in the event.detail.state
object as follows:event.detail.state["key"] = value;
The key can be any string, as long as that string isn't the same as the ID of one of the widgets on the Form.
In the code that handles the olcotgrestorestate
event, use the same key to retrieve the stored information.
The following sample saves the value "test" using "myString" as the key, when the Form is saved:
window.addEventListener("olcotgsavestate", function(event) {
event.detail.state["myString"] = "test";
});
The following code retrieves the value that was stored with the myString
key and displays it in a paragraph (a <p> element) at the top of the form.
window.addEventListener("olcotgrestorestate", function(event) {
var value = event.detail.state["myString"];
$("form p").html(value);
};
Note: When you've used jQuery to register for the events - $(window).on()
- you must use event.originalEvent
in the event handler functions, for example:
$(window).on("olcotgsavestate", function(event) {
event.originalEvent.detail.state["mywidget"] = "test";
});
Restoring widgets
When a COTG Form is reopened, the app restores all input fields and widgets that were already present in the original Form (i.e. the Form deployed via Workflow or sent as test using the Designer). Dynamically added widgets don't get restored. To restore dynamically added widgets, you have to:
- Save information that reveals which widgets were added dynamically, and save the values of their input fields.
This code should go in the event handler for theolcotgsavestate
event. - Add and initialize the widgets again after the Form is reopened. Make sure to put any saved values back in the HTML.
This code should go in the event handler for theolcotgrestorestate
event. - Trigger the
restore-state.cotg
event on the newly added widget, to make sure that it is displayed correctly. For example:$('#myCamera").trigger('restore-state.cotg', event.detail.state);
Put this code in the event handler for theolcotgrestorestate
. event.
Note that the widget must have the same ID as before in order to be able to retrieve its state.
For a detailed example, see: Saving and restoring Camera widgets.
Example
Saving and restoring Camera widgets
This example demonstrates a way to save and restore dynamically added Camera widgets. How to add Camera widgets is explained in another topic: Dynamically adding COTG widgets.
When a user takes or selects a picture with a Camera widget, the COTG app stores the path to the image that was taken or selected in a hidden input. This is the path to the image on the device that runs the COTG app. On submitting the Form the COTG app replaces this value - the path - with the actual image data.
In this example the hidden fields of dynamically added Camera elements have got the .camera-dyn
class. In the event handler for the olcotgsavestate
event, the jQuery each()
method is used to iterate over all inputs that have this class, storing their name and value in an object.
Next, this object is stored - in JSON format - in the event.detail.state
data with the key my-camera-data
.
window.addEventListener('olcotgsavestate', function(event) {
var camObj = {};
$('input.camera-dyn').each(function(){
var camera = $(this).attr('name');
var val = $(this).val();
camObj[camera] = val;
});
event.detail.state['my-camera-data'] = JSON.stringify(camObj);
});
In the olcotgrestorestate
event handler the previously stored JSON is read from the event.detail.state
and parsed into a JavaScript object. A for ... in
loop is then used to iterate over the keys (the camera names) in that object. Inside this loop the cameras are added by calling the addCamera()
function with the ID and value (the path to the picture) of each Camera element. Subsequently the restore-state.cotg
event of the new widget is called to make sure that the thumbnail of the picture is shown and the Clear button becomes visible.
window.addEventListener('olcotgrestorestate', function(event) {
var json = JSON.parse(event.detail.state['my-camera-data']);
for (var cameraID in json) {
var value = json[cameraID];
addCameraWidget(cameraID,value);
$('#' + cameraID).trigger('restore-state.cotg', event.detail.state);
}
});
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