Skip to main content

Form Lifecycle Events

Form lifecycle events allow you to hook into key moments in a form's existence: when it loads, saves, or closes.

Event Types

EventTriggered When
onLoadForm finishes loading/rendering
onSaveForm save is triggered
onCloseForm is about to close
onBeforeSaveBefore form data is saved (validation)

onLoad Event

Triggered: When the form finishes loading and all widgets are initialized Use For: Initialize form data, load dropdown options, set default values

Request Example

{
"widgetName": "form",
"widgetEvent": "onLoad",
"formData": {},
"formCode": "CUSTOMERFORM",
"guid": "new"
}

Load Initial Data

if (widgetName == "FORM" && eventType == "ONLOAD")
{
var guid = requestBody.GetProperty("guid").GetString();

if (guid != "new")
{
// Load existing record
var customer = await _dbContext.Customers
.FirstOrDefaultAsync(c => c.Id.ToString() == guid);

if (customer != null)
{
formData["customerName"] = customer.Name;
formData["email"] = customer.Email;
formData["phone"] = customer.Phone;
formData["address"] = customer.Address;
formData["status"] = customer.StatusId.ToString();
response["formData"] = formData;
}
}
else
{
// Set default values for new record
formData["status"] = "1"; // Default to "New" status
formData["createdDate"] = DateTime.Now.ToString("yyyy-MM-dd");
formData["country"] = "US"; // Default country
response["formData"] = formData;
}

// Load dropdown options
var statuses = await _dbContext.Statuses.ToListAsync();
var countries = await _dbContext.Countries.ToListAsync();

response["fieldAllowedValues"] = new Dictionary<string, object>
{
{
"status", statuses.ToDictionary(
s => s.Id.ToString(),
s => s.Name
)
},
{
"country", countries.ToDictionary(
c => c.Code,
c => c.Name
)
}
};
}

Set Widget Visibility Based on Permissions

if (widgetName == "FORM" && eventType == "ONLOAD")
{
// Get current user permissions
var userId = requestBody.GetProperty("userId").GetString();
var user = await _dbContext.Users.FindAsync(userId);

var visibility = new Dictionary<string, bool>();
var readOnly = new Dictionary<string, bool>();

if (user.Role == "Viewer")
{
// Viewers can only see limited fields
visibility["sensitiveData"] = false;
visibility["financialInfo"] = false;

// Make all fields read-only
readOnly["customerName"] = true;
readOnly["email"] = true;
readOnly["phone"] = true;
}
else if (user.Role == "Editor")
{
// Editors can see all but can't edit sensitive data
visibility["sensitiveData"] = true;
visibility["financialInfo"] = true;

readOnly["sensitiveData"] = true;
}
// Admin has full access (no restrictions)

response["widgetsState"] = new
{
visibility = visibility,
readOnly = readOnly
};
}

onSave Event

Triggered: When form save is triggered (usually by a save button) Use For: Validate data, save to database, trigger workflows

Request Example

{
"widgetName": "form",
"widgetEvent": "onSave",
"formData": {
"customerName": "John Doe",
"email": "john@example.com"
},
"formCode": "CUSTOMERFORM",
"guid": "abc123"
}

Save Form Data with Validation

if (widgetName == "FORM" && eventType == "ONSAVE")
{
var feCommands = (List<object>)response["feCommand"];

// Validate required fields
var errors = new List<string>();

if (string.IsNullOrEmpty(formData.GetValueOrDefault("customerName", "").ToString()))
errors.Add("Customer name is required");

if (string.IsNullOrEmpty(formData.GetValueOrDefault("email", "").ToString()))
errors.Add("Email is required");

if (errors.Any())
{
feCommands.Add(new
{
command = "ShowMessage",
args = new
{
type = "error",
message = string.Join(", ", errors)
}
});
return Ok(response);
}

var guid = requestBody.GetProperty("guid").GetString();

try
{
if (guid == "new")
{
// Create new customer
var customer = new Customer
{
Id = Guid.NewGuid(),
Name = formData["customerName"].ToString(),
Email = formData["email"].ToString(),
Phone = formData.GetValueOrDefault("phone", "").ToString(),
Address = formData.GetValueOrDefault("address", "").ToString(),
CreatedAt = DateTime.UtcNow
};

await _dbContext.Customers.AddAsync(customer);
}
else
{
// Update existing customer
var customer = await _dbContext.Customers.FindAsync(Guid.Parse(guid));

if (customer != null)
{
customer.Name = formData["customerName"].ToString();
customer.Email = formData["email"].ToString();
customer.Phone = formData.GetValueOrDefault("phone", "").ToString();
customer.Address = formData.GetValueOrDefault("address", "").ToString();
customer.UpdatedAt = DateTime.UtcNow;

_dbContext.Customers.Update(customer);
}
}

await _dbContext.SaveChangesAsync();

// Show success message
feCommands.Add(new
{
command = "ShowMessage",
args = new { type = "success", message = "Customer saved successfully!" }
});

// Close form
feCommands.Add(new
{
command = "CloseForm",
args = new { }
});
}
catch (Exception ex)
{
feCommands.Add(new
{
command = "ShowMessage",
args = new { type = "error", message = $"Error saving customer: {ex.Message}" }
});
}
}

onClose Event

Triggered: When form is about to close Use For: Clean up resources, confirm unsaved changes, log activity

Request Example

{
"widgetName": "form",
"widgetEvent": "onClose",
"formData": {
"customerName": "John Doe"
},
"formCode": "CUSTOMERFORM",
"guid": "abc123"
}

Log Form Activity

if (widgetName == "FORM" && eventType == "ONCLOSE")
{
// Log activity
var activityLog = new ActivityLog
{
Id = Guid.NewGuid(),
UserId = requestBody.GetProperty("userId").GetString(),
FormCode = requestBody.GetProperty("formCode").GetString(),
RecordId = requestBody.GetProperty("guid").GetString(),
Action = "FormClosed",
Timestamp = DateTime.UtcNow
};

await _dbContext.ActivityLogs.AddAsync(activityLog);
await _dbContext.SaveChangesAsync();
}

Best Practices

  1. onLoad - Use for initialization only, avoid heavy computations
  2. onSave - Always validate data before saving
  3. Handle errors gracefully - Provide clear error messages to users
  4. Use transactions - For operations that modify multiple tables
  5. Log important events - Track form opens, saves, and closes for audit trails

Next Steps