The {create:...} macro provides an easy way to add "Create New" functionality to any report or page.
{create:workflow}
Result: Button labeled "+ Create Workflow" that opens a modal form
{create:workflow:+ New Workflow:Create New Workflow:Save}
Result: Button labeled "+ New Workflow", modal title "Create New Workflow", submit button "Save"
{create:workflow::::EditWorkflow:workflows}
Result: Default labels, submits to EditWorkflow RPC, refreshes "workflows" report after save
{create:TYPE:BUTTON:TITLE:SUBMIT:RPC:REFRESH}
| Position | Parameter | Required | Default | Description |
|---|---|---|---|---|
| 1 | TYPE | ✓ | - | Object type from ObjTextCreate.yaml |
| 2 | BUTTON | + Create <Type> |
Button label text | |
| 3 | TITLE | Create <Type> |
Modal header title | |
| 4 | SUBMIT | Save |
Submit button label | |
| 5 | RPC | From YAML | RPC handler/report code | |
| 6 | REFRESH | None | Report to refresh after save |
Define object types in factory.text/package.core/ObjTextCreate.yaml:
create:
workflow:
report_code: EditWorkflow
table: def_workflow
title_field: WorkflowName
fields:
WorkflowName:
label: Workflow Name
type: text
required: true
placeholder: workflow_name
Description:
label: Description
type: textarea
required: false
rows: 3
UserGroup:
label: User Group
type: select
required: true
default: ALL
options:
- ALL
- ADMIN
- USER
Active:
label: Active
type: checkbox
required: false
default: true
| Type | HTML Input | Example |
|---|---|---|
text |
<input type="text"> |
Short text input |
textarea |
<textarea> |
Multi-line text |
email |
<input type="email"> |
Email address |
password |
<input type="password"> |
Password field |
number |
<input type="number"> |
Numeric input |
date |
<input type="date"> |
Date picker |
select |
<select> |
Dropdown list |
checkbox |
<input type="checkbox"> |
Boolean checkbox |
radio |
<input type="radio"> |
Radio button group |
| Property | Type | Required | Description |
|---|---|---|---|
label |
string | ✓ | Field label text |
type |
string | ✓ | Input type (see above) |
required |
boolean | Is field required? | |
placeholder |
string | Placeholder text | |
default |
any | Default value | |
rows |
number | Rows for textarea | |
min |
number | Min value for number | |
max |
number | Max value for number | |
options |
array | Options for select/radio | |
pattern |
string | Regex validation pattern | |
help |
string | Help text below field |
Your report must implement a save method that accepts the form data:
class ReportEditWorkflow(Report):
def save(self, data):
"""Handle create modal form submission."""
workflow_name = data.get("WorkflowName", "")
description = data.get("Description", "")
user_group = data.get("UserGroup", "ALL")
# Validate
if not workflow_name:
return {"success": False, "error": "Workflow name required"}
# Save to database
sql = f"""
INSERT INTO def_workflow (WorkflowName, Description, UserGroup, Package)
VALUES ('{self.escape_sql(workflow_name)}',
'{self.escape_sql(description)}',
'{self.escape_sql(user_group)}',
'{self.Package}')
"""
try:
self.sql_execute(sql)
return {"success": True, "message": "Workflow created"}
except Exception as e:
return {"success": False, "error": str(e)}
When you specify a refresh_report parameter, the modal will:
save method{"success": true}):
getlist on the refresh reportExample flow:
{create:workflow::::EditWorkflow:workflows}
↓
User clicks "+ Create Workflow"
↓
Modal opens with form fields
↓
User fills form and clicks "Save"
↓
POST to /rpc/ → EditWorkflow.save(data)
↓
Response: {"success": true, "message": "Created"}
↓
Modal closes
↓
RPC call: workflows.getlist()
↓
Table refreshes with new data
Add create button above a SmartTable report:
<div class="report-toolbar">
{create:workflow:+ New:Create Workflow:Save:EditWorkflow:workflows}
</div>
{smarttable:workflows}
Different object types on the same page:
{create:workflow:+ Workflow::::EditWorkflow:workflows}
{create:webhook:+ Webhook::::EditWebhook:webhooks}
{create:calculation:+ Calculation::::EditCalculation:calculations}
Use empty labels and add your own HTML:
<button class="btn btn-primary" onclick="document.querySelector('[data-create-workflow]').click()">
<i class="icon-plus"></i> Create New Workflow
</button>
{create:workflow::::::workflows}
Use report logic to conditionally show create buttons:
def Render(self):
html = '<div class="toolbar">'
if self.User in self.get_admins():
html += '{create:workflow::::EditWorkflow:workflows}'
html += '</div>'
return html
Client-side validation is automatic based on field properties:
required: true → Field cannot be emptytype: email → Must be valid email formattype: number → Must be numericmin/max → Value must be in rangepattern → Must match regexServer-side validation in your save method:
def save(self, data):
errors = []
# Required fields
if not data.get("WorkflowName"):
errors.append("Workflow name is required")
# Length validation
if len(data.get("Description", "")) > 500:
errors.append("Description too long (max 500 chars)")
# Custom validation
if self.workflow_exists(data.get("WorkflowName")):
errors.append("Workflow name already exists")
if errors:
return {"success": False, "error": ", ".join(errors)}
# ... save logic ...
The modal automatically handles errors from the RPC response:
# Success - modal closes
return {"success": True, "message": "Workflow created successfully"}
# Error - shows error message, modal stays open
return {"success": False, "error": "Workflow name already exists"}
# Warning - shows warning, modal stays open
return {"success": False, "warning": "Created with warnings"}
The modal uses standard Bootstrap classes by default. Customize with CSS:
/* Modal container */
.create-modal {
max-width: 600px;
}
/* Form fields */
.create-modal .form-group {
margin-bottom: 1rem;
}
/* Submit button */
.create-modal .btn-submit {
background-color: #007bff;
color: white;
}
/* Error messages */
.create-modal .error {
color: #dc3545;
}
Enable debug logging in ObjTextCreate.py:
DO_DEBUG = True
Check console for:
factory.text/package.core/ObjTextCreate.md - Complete documentationfactory.text/package.core/ObjTextCreate.yaml - Object type definitionsresource.notes/workflow_simulation_guide.md - Workflow-specific usageresource.web/javascript/axion.rpc.js - RPC client implementation