Collecting response data
To collect response data from the form runner, you need to use the onSubmit
event. This event fires when the form completes and the response data is ready for further processing. You can also use this event to supply feedback to the runner about whether the data processing was successful or not. This guide shows you how to use the event and set up data retrieval properly.
To retrieve response data you need to use one of the export functions. Have a look at the Export
module for a list of all available export functions and detailed documentation.
đĨ Basic data collectionâ
The following example shows how to use the onSubmit
event. As you can see the supplied function receives a reference to the active form instance. By using one of the supplied Export
functions from the Runner library you can retrieve the data in a convenient format. The following example shows how to export the data using the exportables
or CSV
function.
- Autoscroll
- Chat
- Classic
import { run } from "@tripetto/runner-autoscroll";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) => {
// This exports all exportable data in the form
const exportables = Export.exportables(instance);
// Iterate through all the fields
exportables.fields.forEach((field) => {
// Output each field name and value to the console
console.log(`${field.name}: ${field.string}`);
});
// This exports the collected data as a CSV object
const csv = Export.CSV(instance);
// Output CSV to the console
console.log(csv.fields);
console.log(csv.record);
}
});
import { run } from "@tripetto/runner-chat";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) => {
// This exports all exportable data in the form
const exportables = Export.exportables(instance);
// Iterate through all the fields
exportables.fields.forEach((field) => {
// Output each field name and value to the console
console.log(`${field.name}: ${field.string}`);
});
// This exports the collected data as a CSV object
const csv = Export.CSV(instance);
// Output CSV to the console
console.log(csv.fields);
console.log(csv.record);
}
});
import { run } from "@tripetto/runner-classic";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) => {
// This exports all exportable data in the form
const exportables = Export.exportables(instance);
// Iterate through all the fields
exportables.fields.forEach((field) => {
// Output each field name and value to the console
console.log(`${field.name}: ${field.string}`);
});
// This exports the collected data as a CSV object
const csv = Export.CSV(instance);
// Output CSV to the console
console.log(csv.fields);
console.log(csv.record);
}
});
See the Runner library documentation for all possible Export functions.
â ī¸ Error handlingâ
In most situations, the onSubmit
event is the best place to transmit data to an endpoint like an API. Usually, this is an asynchronous action that might fail in some situations (like losing the connection during transmission). You can supply feedback about the operation to the runner. That way, the user sees a visual indication while data is transferring. When something goes wrong, an error/retry message pops up. To use this feature, construct a Promise
as shown in the following example:
- Autoscroll
- Chat
- Classic
import { run } from "@tripetto/runner-autoscroll";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) =>
new Promise((resolve, reject) => {
// This example uses fetch to post data to an endpoint
fetch("/example-server", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(Export.exportables(instance)),
})
.then((response) => {
if (response.ok) {
// All good, resolve the promise
resolve();
} else {
// Not so good, reject the promise
reject("rejected");
}
})
.catch((error) => {
// Error occurred, reject with error message
reject(error.message);
});
}),
});
import { run } from "@tripetto/runner-chat";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) =>
new Promise((resolve, reject) => {
// This example uses fetch to post data to an endpoint
fetch("/example-server", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(Export.exportables(instance)),
})
.then((response) => {
if (response.ok) {
// All good, resolve the promise
resolve();
} else {
// Not so good, reject the promise
reject("rejected");
}
})
.catch((error) => {
// Error occurred, reject with error message
reject(error.message);
});
}),
});
import { run } from "@tripetto/runner-classic";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) =>
new Promise((resolve, reject) => {
// This example uses fetch to post data to an endpoint
fetch("/example-server", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(Export.exportables(instance)),
})
.then((response) => {
if (response.ok) {
// All good, resolve the promise
resolve();
} else {
// Not so good, reject the promise
reject("rejected");
}
})
.catch((error) => {
// Error occurred, reject with error message
reject(error.message);
});
}),
});
Reject error codesâ
The reject function supports two particular error codes:
outdated
: This indicates to the runner that the current form is an outdated version (this allows the runner to propagate theonReload
event to try to load the most recent version of the form);rejected
: This indicates that the data is rejected and not saved by the endpoint.
You can feed those error values to the reject function:
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) => new Promise((resolve, reject) => {
// This example indicates the runner that the form is outdated
reject("outdated");
})
});
Any other value provided to the reject function is considered a descriptive error message. The runner outputs this error message in the browser console. The respondent will see a common error message without technical details in it.
â Validating the response dataâ
Tripetto contains built-in functions to make it easy to validate the response data. Static validation using the available JSON Schema is also possible. Read the Validating response data guide to learn more.
âŠī¸ Feedback to the runnerâ
It is possible to feed an identifier or reference associated with the submitted response data back to the runner. Tripetto allows using this identifier in the closing message of a form. It can be presented to the user or used in the redirect URL. To do so, supply the identifier or reference to the resolve
function of the promise.
- Autoscroll
- Chat
- Classic
import { run } from "@tripetto/runner-autoscroll";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) => new Promise((resolve, reject) => {
// This returns the identifier `TEST123` to the runner
resolve("TEST123");
})
});
import { run } from "@tripetto/runner-chat";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) => new Promise((resolve, reject) => {
// This returns the identifier `TEST123` to the runner
resolve("TEST123");
})
});
import { run } from "@tripetto/runner-classic";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) => new Promise((resolve, reject) => {
// This returns the identifier `TEST123` to the runner
resolve("TEST123");
})
});
âšī¸ Exportable vs. actionable dataâ
Tripetto supports two types of data collections that are retrieved from a form:
- Exportable data: These are all the fields in the form that are marked as exportable by the form creator;
- Actionable data: These fields are generated by action blocks that can perform certain actions like sending an email message.
The exportable data is the most important data collection as it includes all the fields that usually need to be stored. There is a special function called exportables
to make it easy to retrieve those fields. So, a common setup would be to retrieve this data collection and submit it to an endpoint as this is the response data that should be saved in most cases.
The actionable data, on the other hand, is volatile data required for performing actions when the form completes. It often needs to be transferred to an API or endpoint to allow further processing. One of the most common actions is post-processing the Mailer block. This block allows form creators to compose email messages in the form. It is a powerful feature, but it needs additional work to get it up and running properly.
Please refer to the Post-processing actions guide for more information and instructions to set it up.
đŠâđģ Simple AJAX exampleâ
The actual saving of form response data to a data store is entirely up to you. You could, for example, use an AJAX call to post the data to a server.
- fetch()
- XMLHttpRequest
- SuperAgent
- Axios
import { run } from "@tripetto/runner-autoscroll";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) =>
new Promise((resolve, reject) => {
fetch("/example-server", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(Export.exportables(instance)),
})
.then((response) => {
if (response.ok) {
// All good, resolve the promise
resolve();
} else {
// Not so good, reject the promise
reject();
}
})
.catch((error) => {
// Error occurred, reject with error message
reject(error.message);
});
}),
});
import { run } from "@tripetto/runner-autoscroll";
import { Export } from "@tripetto/runner";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) =>
new Promise((resolve, reject) => {
const httpRequest = new XMLHttpRequest();
httpRequest.addEventListener("load", () => resolve());
httpRequest.addEventListener("error", () => reject());
httpRequest.addEventListener("abort", () => reject());
httpRequest.open("POST", "/example-server");
httpRequest.send(JSON.stringify(Export.exportables(instance)));
}),
});
import { run } from "@tripetto/runner-autoscroll";
import { Export } from "@tripetto/runner";
import { post } from "superagent";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) =>
new Promise((resolve, reject) => {
post("/example-server")
.send(Export.exportables(instance))
.then((response) => {
if (response.ok) {
// All good, resolve the promise
resolve();
} else {
// Not so good, reject the promise
reject();
}
})
.catch((error) => {
// Error occurred, reject with error message
reject(error.message);
});
}),
});
import { run } from "@tripetto/runner-autoscroll";
import { Export } from "@tripetto/runner";
import { post } from "axios";
run({
definition: /* Supply your form definition here */,
onSubmit: (instance) =>
new Promise((resolve, reject) => {
post("/example-server", Export.exportables(instance))
.then((response) => {
if (response.status == 200) {
// All good, resolve the promise
resolve();
} else {
// Not so good, reject the promise
reject();
}
})
.catch((error) => {
// Error occurred, reject with error message
reject(error.message);
});
}),
});
đ Referenceâ
- Autoscroll
- Chat
- Classic
Have a look at the complete autoscroll runner API reference for detailed documentation. In the examples above, the following symbols were used:
Have a look at the complete chat runner API reference for detailed documentation. In the examples above, the following symbols were used:
Have a look at the complete classic runner API reference for detailed documentation. In the examples above, the following symbols were used: