Chapter 3. $fh.forms

3.1. $fh.forms.getForms

$fh.forms.getForms(options, callback);

Return an array of JSON objects with form summary information.

Note

These form summary JSON objects do not contain the full form definition. Use the $fh.forms.getForm function to get a full form definition.

3.1.1. Example

//Get a list of forms associated with the project.
var options = {

};

$fh.forms.getForms(options,

/*
* Function executed with forms.
*/
function (err, response) {
  if (err) return handleError(err);

  //An Array Of Forms Associated With The Project
  var formsArray = response.forms;

   /*
     exampleForm: {
      _id: <<Form Id>>,
      name: <<Form Name>>,
      description: <<Form Description>>
      lastUpdatedTimestamp: <<Timestamp of when the form was last updated>>
    }
  */
  var exampleForm = formsArray[0];

  return callback(undefined, formsArray);
});

3.2. $fh.forms.getForm

  $fh.forms.getForm(options, callback)

3.2.1. Details

Retrieve specific form model based on form ID. Form IDs can be obtained using the $fh.forms.getForms function.

3.2.2. Example

$fh.forms.getForm({
  "_id": formId
}, function (err, form) {
  if (err) return handleError(err);


  /*
    A JSON object describing a full form object.
  */
  return callback(undefined, form);
});

3.3. $fh.forms.getPopulatedFormList

  $fh.forms.getPopulatedFormList(options, callback)

3.3.1. Details

Retrieve form models based on a list of form IDs.

3.3.2. Example

$fh.forms.getPopulatedFormList({
  "formids": [formId1, formId2 ... ]
}, function (err, arrayOfForms) {
  if (err) return handleError(err);


  /*
    A JSON object describing a full form object.
  */
  return callback(undefined, arrayOfForms);
});

3.4. $fh.forms.getSubmissions

  $fh.forms.getSubmissions(options, callback)

3.4.1. Details

List all Submissions based on filtering criteria

3.4.2. submissionsObject

{
  submissions: [<SubmissionJSON>, <SubmissionJSON>]
}

3.4.3. Example

$fh.forms.getSubmissions({
  "formId": [formId1, formId2 ... ],
  "subid": [subId1, subId2 ...]
}, function (err, submissionsObject) {
  if (err) return handleError(err);


  /*
    An Object Containing An Array of JSON objects describing a full Submission object.
  */
  return callback(undefined, submissionsObject);
});

3.5. $fh.forms.getSubmission

  $fh.forms.getSubmission(options, callback)

3.5.1. Details

Get A Single Form Submission

3.5.2. Example

$fh.forms.getSubmissions({
  "submissionId": subId1
}, function (err, submission) {
  if (err) return handleError(err);


  /*
    A JSON object describing a full Submission object.
  */
  return callback(undefined, submission);
});

3.6. $fh.forms.getSubmissionFile

  $fh.forms.getSubmissionFile(options, callback)

3.6.1. Details

Stream a single file contained in a submission. Files are accessed using the fileGroupId field in a submission file field.

3.6.2. fileStreamObject

{
  stream: <Readable File Stream>
}

3.6.3. Example

$fh.forms.getSubmissionFile({
  "_id": fileGroupId
}, function (err, fileStreamObject) {
  if (err) return handleError(err);


  /**
  * Pipe the file stream to a writable stream (for example, a FileWriter)
  */
  fileStreamObject.stream.pipe(writable_stream);
  fileStreamObject.stream.resume();
});

3.7. Form JSON Definition

A form JSON object contains all of the information needed to process a form.

{
   "_id":"<<24 Character Form ID>>",
   "description":"This is an example form definition",
   "name":"Example Form",
   "updatedBy":"<<User ID of the person that last updated the form>>",
   "lastUpdatedTimestamp":1410876316105, //Time the form was last updated.
   "subscribers":[
   //Email addresses to be notified when a submission has been made against this form.
    "notifiedUser1@example.com",
    "notifiedUser2@example.com"
   ],
   "pageRules":[
      <<Page Rule JSON Object>>
   ],
   "fieldRules":[
      <<Field Rule JSON Object>>
   ],
   "pages":[
      <<Page JSON Object>>,
   ],
   //Convenient reference for the index of a page with <<Page Id>> in the "pages" array.
   "pageRef":{
      "<<Page Id>>":0,
      "<<Page Id>>":1
   },
   //Convenient reference for the index of a field. Both the page index and field index are given.
   "fieldRef":{
      "<<Field Id>>":{
         "page":0,
         "field":0
      },
      "<<Field Id>>":{
         "page":0,
         "field":1
      }
   }
}

3.7.1. Page

{
   "_id":"<<Page ID>>",
   "name":"Page 1",
   "fields":[
      <<Field JSON Object>>
   ]
}

3.7.2. Field

{
  "_id":"<<Field ID>>",
   "required":true,
   "type":"text",//Field Type
   "name":"A Sample Text Field",
   "repeating":false/true //Boolean that describes if a field is repeating or not.
   "fieldOptions":{
      "validation":{ // Optional validation parameters for the form.
         "validateImmediately":true //Flag for whether field inputs should be immediately validated (for example, On-Blur on a Client App.)
      },
      "definition": {// Optional definition options.
          "minRepeat": 2, //Minimum number of entries for this field.
          "maxRepeat": 5 //Maximum number of entries for this field.
      }
   }
}

3.7.3. Page Rule

This JSON object describes a Page Rule created in the Studio.

{
   "type":"skip",//A "skip" or "show" page rule
   "_id":"<<ID of the Page Rule>>",
   "targetPage":[
      "<<ID of the Page targeted by the Page Rule>>"
   ],
   "ruleConditionalStatements":[
      {
         "sourceField":"<<ID of the Field this condition is sourcing data from>>",
         "restriction":"is",// Comparator operator for the conditional statement.
         "sourceValue":"skippage" //Value To Compare.
      }
   ],
   //Combinator for "ruleConditionalStatements".  Can be "and" or "or".
   "ruleConditionalOperator":"and",
}

3.7.4. Field Rule

This JSON object describes a Field Rule created in the Studio.

{
   "type":"hide/show", //A "hide" or "show" field rule
   "_id":"<<ID of the Field Rule>>",
   "targetField":[
      "<<ID of the Field targeted by the Field Rule>>"
   ],
   "ruleConditionalStatements":[
      {
         "sourceField":"<<ID of the Field this condition is sourcing data from>",
         "restriction":"is",// Comparator operator for the conditional statement.
         "sourceValue":"hideMe" //Value To Compare.
      }
   ],
   //Combinator for "ruleConditionalStatements".  Can be "and" or "or".
   "ruleConditionalOperator":"and"
}

3.8. $fh.forms.getTheme

  $fh.forms.getTheme(options, callback)

3.8.1. Details

Loads a JSON object representing the Theme that is assigned to the Project.

3.8.2. Example

//Currently no parameters for loading a theme.
var options = {

};

$fh.forms.getTheme({}, function (err, theme) {
  if (err) return handleError(err);

  return callback(undefined, theme);
});

3.8.3. $fh.forms.getAppClientConfig

  $fh.forms.getAppClientConfig(options, callback)

3.8.4. Details

Returns a JSON object containing Client Config settings associated with the Project. These are configured in the Studio.

3.8.5. Example

//Currently no options for loading app config.
var options = {

};

$fh.forms.getAppClientConfig(options, function (err, clientConfig) {
  if (err) return handleError(err);


  return callback(undefined, clientConfig);
});

3.8.6. Client Config JSON Object

{
  "sent_items_to_keep_list": [5, 10, 20, 30, 40, 50, 100], //Array representing options available to
  "targetWidth": 480, //Camera Photo Width
  "targetHeight": 640, //Camera Photo Height
  "quality": 75, //Camera Photo Quality
  "debug_mode": false, //Set the Client To Debug Mode
  "logger" : false, //Client Logging
  "max_retries" : 0, //Maximum number of failed uplod attempts before returning an error to the user
  "timeout" : 30,// Number of seconds before a form upload times out.
  "log_line_limit": 300,//Maximum number of log entries before rotating logs
  "log_email": "test@example.com" //The email address that logs are sent to.
}

3.9. $fh.forms.submitFormData

   $fh.forms.submitFormData(options, callback)

3.9.1. Details

Submits a JSON object representing a Form Submission.

3.9.1.1. Example

var options = {
  "submission": <<Submission JSON Object>>,
  "appClientId": <<ID Of The Client Making The Submission.>>
};

$fh.forms.submitFormData(options, function(err,data){
  if(err) return callback(err);

  return callback(null,data);
});

3.9.2. Submission JSON Object

{
  "formId": "<<ID Of Form Submitting Agains>>",
  "deviceId": "<<ID of the device submitting the form>>",
  "deviceIPAddress": "<<IP Address of the device submitting the form>>",
  "formFields": [<<Field Entry JSON Object>>],
  "deviceFormTimestamp": "<<lastUpdatedTimestamp of the Form that the submission was submitted against.>>",
  "comments": [{ //Optional comments related to the submission
    "madeBy": "user",
    "madeOn": "12/11/10",
    "value": "This is a comment"
  }]
}

3.9.3. Field Entry JSON Object

{
  fieldId: <<ID Of The Field "fieldValues" Are Submitted Against>>,
  fieldValues: [<<Field Value Entry>>]
}

3.9.4. Field Value Entries

This presents the data format required for each type of field submission.

  • Text: String
  • TextArea: String
  • Number: Number
  • Radio: String (Must represent one of the Radio Field options defined in the Form)
  • Dropdown: String (Must represent one of the Dropdown options represented in the Form)
  • Webstite: String
  • Email: String (Must be a valid email format)
  • DateStamp - Date Only: String (Format: DD/MM/YYYY)
  • DateStamp - Time Only: String (Format: HH:SS)
  • DateStamp - Date & Time: String (Format: YYYY-MM-DD HH:SS)

Check boxes

{
  selections: ["Check box Option 1", .... , "Check box Option 4"]
}

Location (And Map Field) - Latitude & Longitude

{
  lat: <<Valid Latitude Value>,
  long: <<Valid Longitude Value>>
}

Location - Northings & Eastings

{
  zone: "11U",
  eastings: 594934,
  northings: 5636174
}

File Based Fields - File, Photo, Signature

{
  fileName: <<Name of the file to be uploaded>>,
  fileType: <<Valid mime type of the file>>,
  fileSize: <<Size of the file in Bytes>>,
  fileUpdateTime: <<Timestamp of the time the file was saved to device>>,
  hashName: "filePlaceHolder12345" //A unique identifer for the fole. NOTE: Must begin with "filePlaceHolder"
}
Note

All hashName parameters must begin with filePlaceHolder or the submission will be rejected.

3.10. $fh.forms.getSubmissionStatus

  $fh.forms.getSubmissionStatus(options, callback)

3.10.1. Details

Returns the current status of the submission.

3.10.2. Example

var options = {
  submission: {
    //This is the submission ID returned when the $fh.forms.submitFormData function returns.
    submissionId: "<<Remote Submission ID>>"
  }
};

$fh.forms.getSubmissionStatus(options, function(err, submissionStatus){
   if(err) return handleError(err);

  return callback(undefined, submissionStatus);
});

3.10.3. Submission Status JSON Object

Note

A submission is only marked as complete after the $fh.forms.completeSubmission function has been called. Therefore it is possible that the pendingFiles array can be empty and the status set as pending.

{
  "status": "pending/complete", //Status can either be pending or complete
  "pendingFiles": [
    "<<hashName of file not uploaded yet. (for example, filePlaceHolder1234)>>"
  ]
}

3.11. $fh.forms.submitFormFile

  $fh.forms.submitFormFile(options, callback)

3.11.1. Details

Uploads a file to the submission.

Note

The file must already be added to the Submission JSON Object and submitted using the $fh.forms.submitFormData function.

Note

The file must already exist on the local file system to upload it to the submission.

Warning

If the keepFile parameter is not set to true, the file uploaded to the submission will be deleted from the file system when upload is complete.

3.11.2. Example

var options = {
  "submission": {
    "fileId": "<<The File hashName>>",
    "submissionId": "<<The Submission ID Containing The File Input>>",
    "fieldId": "<<Field Id The File Is Being Submitted Against>>",
    "fileStream": "<</path/to/the/file/stored/locally>>" //path to the file
    "keepFile": true/false //Keep the file storated at "fileStream" when it has been uploaded.
  }
 }

$fh.forms.submitFormFile(options, function(err, submitFileResult){
  if(err) return handleError(err);

  //File upload has completed successfully
  return callback(undefined, submitFileResult);
});

3.11.3. submitFileResult JSON Object

{
  status: 200 //Indicating that the file has uploaded successfully
  savedFileGroupId: <<Server ID of the file held in the submission>>
}

3.12. $fh.forms.completeSubmission

  $fh.forms.completeSubmission(options, callback)

3.12.1. Details

Mark the submission as complete. This will check that all of the files submitted as part of the Submission JSON have been uploaded.

If the submission has completed successfully, the completeResult JSON object will contain

{
  "status": "complete"
}

If submitted files have not been uploaded the completeResult JSON object will contain

{
  "status": "pending",
  "pendingFiles": [
    "<<hashName of file not uploaded yet. (for example, filePlaceHolder1234)>>"
  ]
}

3.12.2. Example

var options = {
  "submission": {
      "submissionId": "<<The ID of the Submission to Complete>>"
    }
}

$fh.forms.completeSubmission(options, function (err, completeResult) {
  if (err) return handleError(err);

  return callback(undefined, completeResult);
});

3.13. $fh.forms.createSubmissionModel

3.13.1. Details

The $fh.forms.createSubmissionModel function is an alternative method of creating and submitting a form.

The Submission Model provides some convenience functions to make the process of creating a submission easier.

3.13.2. Example

var options = {
  "form": <<A Form JSON Object Obtained using $fh.forms.getForm>>
};

$fh.forms.createSubmissionModel(options, function(err, submissionModel){
  if (err) return handleError(err);

  //Now use the Submisison Model Functions To Add data to the Submission
  var fieldInputOptions = {
    "fieldId": "<<The ID of the field To Add Data To>>",
    "fieldCode": "<<The fieldCode of the field To Add Data To>>"
    "index": "<<The index to add the value to>>" //(This is used for repeating fields with mutiple values)
    "value": "<<A valid input value to add to the submission>>"
  };

  //Note: the addFieldInput function is not asynchronous
  var error = submissionModel.addFieldInput(fieldInputOptions);

  if(error){
    return handleError(error);
  }

  /*
  Submitting the data as part of a submission.
  This function will upload all files passed to the submission using the addFieldInput function
  */
  submissionModel.submit(function(err, submissionId){
    if(err) return handleError(err);

    return callback(undefined, submissionId);
  });
});

3.14. $fh.forms.registerListener

Note

The version of fh-mbaas-api in your package.json file must be at least 4.8.0.

3.14.1. Details

The $fh.forms.registerListener function allows you to register an EventEmitter object to listen for submission events that occur.

Note

The $fh.forms.registerListener and $fh.forms.deregisterListener functions only accept EventEmitter objects as parameters.

//NodeJS Events Module. Note, this is required to register event emitter objects to forms.
var events = require('events');
var submissionEventListener = new events.EventEmitter();

$fh.forms.registerListener(submissionEventListener, function(err){
  if (err) return handleError(err);

  //submissionEventListener has now been registered with the $fh.forms Cloud API. Any valid Forms Events will now emit.
});

3.14.2. Event: submissionStarted

This event is emitted whenever a submission has been submitted, validated and saved to the database. This occurs before any files are uploaded as part of the submission.

The object passed to the submissionStarted event contains the following parameters:

{
    "submissionId": "<<24-character submission ID>>",
    "submissionStartedTimestamp": "<<2015-02-04T19:18:58.746Z>>"
}
//NodeJS Events Module. Note, this is required to register event emitter objects to forms.
var events = require('events');
var submissionEventListener = new events.EventEmitter();

submissionEventListener.on('submissionStarted', function(params){
  var submissionId = params.submissionId;
  var submissionStartedTimestamp = params.submissionStartedTimestamp;
  console.log("Submission with ID " + submissionId + " has started at " + submissionStartedTimestamp);
});

$fh.forms.registerListener(submissionEventListener, function(err){
  if (err) return handleError(err);

  //submissionEventListener has now been registered with the $fh.forms Cloud API. Any valid Forms Events will now emit.
});

3.14.3. Event: submissionComplete

This event is emitted whenever a submission has been submitted, has been validated and saved to the database, all files have been saved to the database and the submission has been verified. The submission is now ready for processing using the $fh.forms.getSubmission Cloud API.

//NodeJS Events Module. Note, this is required to register event emitter objects to forms.
var events = require('events');
var submissionEventListener = new events.EventEmitter();

submissionEventListener.on('submissionComplete', function(params){
  var submissionId = params.submissionId;
  var submissionCompletedTimestamp = params.submissionCompletedTimestamp;
  console.log("Submission with ID " + submissionId + " has completed at " + submissionCompletedTimestamp);
});

$fh.forms.registerListener(submissionEventListener, function(err){
  if (err) return handleError(err);

  //submissionEventListener has now been registered with the $fh.forms Cloud API. Any valid Forms Events will now emit.
});

The params object passed to the event contains:

{
    "submissionId": "<<24-character submission ID>>",
    "submissionCompletedTimestamp": "<<2015-02-04T19:18:58.746Z>>",
    "submission": "<<JSON definition of the Completed Submission.>>"
}

3.14.4. Event: submissionError

This event is emitted whenever an error has occurred when making a submission.

//NodeJS Events Module. Note, this is required to register event emitter objects to forms.
var events = require('events');
var submissionEventListener = new events.EventEmitter();

submissionEventListener.on('submissionError', function(error){
  console.log("Error Submitting Form");
  console.log("Error Type: ", error.type);
});

$fh.forms.registerListener(submissionEventListener, function(err){
 if (err) return handleError(err);

 //submissionEventListener has now been registered with the $fh.forms Cloud API. Any valid Forms Events will now emit.
});

3.14.4.1. Submission Error Types

Submission errors fall into different types depending on the reason for the error.

3.14.4.1.1. Validation Error

The submitted data is not valid. The response will be in the following format:

Note

For repeating fields, the error messages will be in the same order as the values entered for the field.

{
  type: 'validationError',
  error: {
       valid: < true / false >,
       < fieldId1 >: {
           valid: < true / false >,
           errorMessages: [
               "Validation Error Message 1",
               "Validation Error Message 2"
           ]
       },
       ....,
       < fieldIdN >: {
           valid: < true / false >,
           errorMessages: [
               "Validation Error Message 1",
               "Validation Error Message 2"
           ]
       }
   }
}
3.14.4.1.2. Other Errors Saving The JSON Definition Of The Submission

There was an unexpected error saving the JSON definition of the submission. This event covers all errors other than validation that can occur when attempting to save the submission (For example, an error occurred when saving the submission to the database).

{
  type: 'jsonError',
  error: < Error message >
}
3.14.4.1.3. File Upload Error

There was an error uploading a file for a submission.

{
  type: 'fileUploadError',
  submissionId: < ID of the submission related to the file upload >,
  fileName: < The name of the file uploaded>,
  error: < Error message >
}

3.15. $fh.forms.deregisterListener

Note

The version of fh-mbaas-api in your package.json file must be at least 4.8.0.

3.15.1. Details

Removes a listener from the $fh.forms Cloud API.

//NodeJS Events Module. Note, this is required to register event emitter objects to forms.
var events = require('events');
var submissionEventListener = new events.EventEmitter();

$fh.forms.registerListener(submissionEventListener, function(err){
  if (err) return handleError(err);

  //submissionEventListener has now been registered with the $fh.forms Cloud API. Any valid Forms Events will now emit.
  submissionEventListener.on('submissionStarted', function(params){
    var submissionId = params.submissionId;
    console.log("Submission with ID " + submissionId + " has started");
  });

  //Removing the listener from the $fh.forms Cloud API.
  $fh.forms.deregisterListener(submissionEventListener);
});

3.16. $fh.forms.exportCSV

Note

The version of fh-mbaas-api in your package.json file must be at least 5.10.0.

3.16.1. Details

Export CSV files from the $fh.forms Cloud API. The export returns a zip file of several CSV files. To filter then use the input value, you can filter by:

  • projectId: The GUID of a project to filter by.
  • submissionId: A single Submission ID or an array of submission IDs to filter by.
  • formId: A single Form ID or and array of form IDs to filter by.
  • fieldHeader: Header text to use in the exported CSV files. The options are name for the name of the field or fieldCode to use the field code defined in the Form Builder.
// This is the input parameter to filter the list of CSV files.
var queryParams = {
  projectId: "projectId",
  submissionId: "submissionId",
  formId: ["formId1", "formId2"],
  fieldHeader: "name"
};

$fh.forms.exportCSV(queryParams, function(err, fileStreamObject) {
  // fileStreamObject is a zip file containing CSV files associated
  // to the form it was submitted against.
  if (err) return handleError(err);
  /**
  * Pipe the file stream to a writable stream (for example, a FileWriter)
  */
  fileStreamObject.pipe(writable_stream);
  fileStreamObject.resume();
});

3.17. $fh.forms.exportSinglePDF

Note

The version of fh-mbaas-api in your package.json file must be at least 5.12.0.

Note

This API is compatible with MBaaS version >=4.1.0 .

3.17.1. Details

Export one PDF file for a given submission from the $fh.forms Cloud API. The export returns a stream file.

var params = {
  submissionId: "submissionId"
};

$fh.forms.exportSinglePDF(params, function(err, fileStreamObject){
  if (err) return handleError(err);
  /**
  * Pipe the file stream to a writable stream (for example, a FileWriter)
  */
  fileStreamObject.pipe(writable_stream);
  fileStreamObject.resume();
});