Fit
Control vs action
Use a control for UI
- Lookup and selection controls
- Configurable tables
- KPI and chart modules
- Guided approval panels
- Compliance blocks
- Rich text or structured input components
- Photo or attachment capture experiences
Use an action for logic
- Validation
- Transformation
- Background data updates
- Workflow logic
- Integration calls
Placement
Supported placements
Approval form
- Make required input obvious
- Avoid cluttering the approval experience
- Respect readonly mode for reviewers
- Save output predictably
- Support audit-friendly display
Data list form
- Bind clearly to record fields
- Support safe editing and validation
- Write structured output into configured fields
- Handle existing record values
- Avoid hidden dependencies on unavailable fields
Dashboard page
- Load data efficiently
- Use pagination for larger data sets
- Read variables or temp variables for filters
- Handle empty and loading states
- Validate dashboard output paths before saving
Configuration
Field binding and parameter patterns
Controls can read field values from fieldsValues, context.getFieldValue(fieldName), and values passed through context.params. Declare real current-form dependencies in requiredFields(params).
| Category | Typical type | Examples | Guidance |
|---|---|---|---|
| Plain text | string | title, label, placeholder | Trim and default safely. |
| Expression value | variable | list ID, filter value, dashboard data | Normalize primitives, arrays, and objects. |
| Writable target | variable | saveToField, outputField | Resolve target key separately from current value. |
| Numeric config | string | pageSize, maxResults | Parse with min, max, and default values. |
| Boolean behavior | variable | multiSelect, showToolbar | Normalize from booleans, strings, numbers, and objects. |
Runtime behavior
Expressions, readonly mode, and save output
Use expression-type parameters for values that may come from fields, variables, temp variables, complex variables, dynamic expressions, or dashboard filters. For ordinary read parameters, value is often the desired runtime value. For writable targets, metadata keys may matter more than value.
- Show existing values clearly in readonly mode
- Disable inputs and block edit handlers in code
- Hide add, remove, upload, capture, or save actions when appropriate
- Make output behavior explicit before persisting
Check for setters such as setFieldValue, setFormFieldValue, setValue, setVariableValue, setTempVariableValue, setDashboardVariableValue, and setPageVariableValue. Mutating fieldsValues should be a last fallback, not a promised persistence path.
Data access
Querying data lists with yeeSDKClient
Use context.modules.yeeSDKClient.lists.queryItems(...) when a control needs records from a Yeeflow data list. Request only the fields the UI needs, include a stable identity field, and handle response shape variations.
const result = await yeeSDKClient.lists.queryItems({
listId,
dataListId: listId,
pageIndex: 1,
pageNo: 1,
pageSize,
fields: selectedFields,
fieldIds: selectedFields,
});Quality bar
Reusable control design principles
- Self-contained and parameter-driven
- Defensive with runtime values
- Clear about setup requirements
- Respectful of readonly mode
- Safe when data is missing
- Consistent with Yeeflow UI patterns
- Documented with setup, examples, limitations, testing, and troubleshooting
Qualified controls should feel like Yeeflow application UI: clear labels, compact helper text, calm colors, visible empty states, useful loading states, predictable buttons, readable tables, and restrained status colors.
Template examples
Review reusable control templates
The Custom Code template library includes practical control examples such as Smart Lookup Picker, Multi-Entry Tag Input, KPI Card Set, and related modules that show complete implementation patterns.