Form - Background
The Form Background widget runs invisibly behind a form page. It has no visible UI but can listen to form field changes, read and write field values, and execute logic in the background. Use it for auto-fill, computed fields, cross-field validation, and conditional workflows.
Availability#
| Apps | Mobile |
|---|---|
| Maintenance, Vendor, Requester, Client, Tenant | No |
When to use#
- Auto-calculating a total when quantity or price fields change
- Auto-filling fields based on a lookup selection (e.g., populate address when a vendor is selected)
- Running cross-field validation (e.g., end date must be after start date)
- Enforcing business rules without modifying the form layout
Triggers#
| Function | Description | Example |
|---|---|---|
| setValue | Sets a form field value | See example below |
| getValue | Gets a form field value (returns a Promise). Primitives (string, number): raw value. Lookup/picklist: { id: number }. | See example below |
| getFormData | Gets all form field data (returns a Promise). Returns record-like object { subject, description, siteId, client, ... }. | window.facilioApp.interface.trigger('getFormData').then(data => { ... }); |
| getFormMeta | Gets form metadata (returns a Promise). Returns { id, name, displayName, sections, fields, moduleId }. | window.facilioApp.interface.trigger('getFormMeta').then(meta => { ... }); |
| setSubFormData | Sets data for a subform | See example below |
| getCurrentRecord | Gets the current record object (for edit forms). Returns the record directly (not wrapped). | window.facilioApp.interface.trigger('getCurrentRecord').then(record => { ... }); |
setValue example
window.facilioApp.interface.trigger('setValue', { fieldName: 'name', value: 'Value set from connected app'});getValue example
window.facilioApp.interface.trigger('getValue', { fieldName: 'name' }) .then(data => { console.log('Field value:', data); });setSubFormData example
const subformData = { subFormId: 1234, subFormValue: [ { name: 'subform record 1' }, { name: 'subform record 2' }, { name: 'subform record 3' } ]};window.facilioApp.interface.trigger('setSubFormData', subformData);Events#
| Event | Description | Example |
|---|---|---|
| form.changed | Fires whenever any form field value changes | app.on('form.changed', (payload) => { ... }); |
| form.{fieldName}.changed | Fires when a specific field value changes | app.on('form.vendor.changed', (fieldValue) => { ... }); |
form.changed payload — { formData: { ... } }. formData has the same structure as getFormData — field names and values (primitives, lookups as { id }, picklists as { id }, etc.).
form.{fieldName}.changed payload — Always { value: ... }. Lookups/picklists: { value: { id: number } }. Other types (string, number, etc.): { value: rawValue } (e.g. { value: "Ex WO 1asdadad" }).
note
Replace {fieldName} with the actual field link name from your Facilio module (e.g., form.vendor.changed, form.siteId.changed).
// Listen to a specific fieldapp.on('form.vendor.changed', (fieldValue) => { console.log('Vendor changed:', fieldValue);});
// Listen to all field changesapp.on('form.changed', (payload) => { const { formData } = payload; // formData: { subject, description, siteId, client, ... } console.log('Form data changed:', formData);});Example — Auto-calculate total from quantity and rate#
var app = new Vue({ el: '#app', created() { window.facilioApp = FacilioAppSDK.init(); window.facilioApp.on('app.loaded', () => { window.facilioApp.on('form.quantity.changed', () => this.recalculateTotal()); window.facilioApp.on('form.rate.changed', () => this.recalculateTotal()); }); }, methods: { async recalculateTotal() { const quantityData = await window.facilioApp.interface.trigger('getValue', { fieldName: 'quantity' }); const rateData = await window.facilioApp.interface.trigger('getValue', { fieldName: 'rate' });
const quantity = parseFloat(quantityData) || 0; const rate = parseFloat(rateData) || 0;
window.facilioApp.interface.trigger('setValue', { fieldName: 'total', value: quantity * rate }); } }});Example — Auto-fill fields from a lookup selection#
var app = new Vue({ el: '#app', created() { window.facilioApp = FacilioAppSDK.init(); window.facilioApp.on('app.loaded', () => { window.facilioApp.on('form.vendor.changed', async (fieldValue) => { await this.handleVendorChange(fieldValue); }); }); }, methods: { async handleVendorChange(fieldValue) { const vendorId = fieldValue?.value?.id;
if (!vendorId) { window.facilioApp.interface.trigger('setValue', { fieldName: 'vendor_phone', value: '' }); window.facilioApp.interface.trigger('setValue', { fieldName: 'vendor_email', value: '' }); return; }
try { const response = await window.facilioApp.api.fetchRecord('vendors', { id: vendorId }); const vendor = response.vendors;
window.facilioApp.interface.trigger('setValue', { fieldName: 'vendor_phone', value: vendor.phone || '' }); window.facilioApp.interface.trigger('setValue', { fieldName: 'vendor_email', value: vendor.email || '' }); } catch (error) { console.error('Failed to fetch vendor details:', error); } } }});