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
| Event | Triggered When |
|---|---|
onLoad | Form finishes loading/rendering |
onSave | Form save is triggered |
onClose | Form is about to close |
onBeforeSave | Before 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
- onLoad - Use for initialization only, avoid heavy computations
- onSave - Always validate data before saving
- Handle errors gracefully - Provide clear error messages to users
- Use transactions - For operations that modify multiple tables
- Log important events - Track form opens, saves, and closes for audit trails
Next Steps
- Button Events - Handle button clicks
- Datatable Events - Handle table interactions
- Frontend Commands - Control the frontend