User Interface Design
What to know
Interfaces are written in SAIL - Appian's expression-based UI language - and saved as interface objects with rule inputs. Components compose inside layouts: a!formLayout for input forms, a!columnsLayout and a!cardLayout for page structure, a!sectionLayout for grouping, and a!gridField with a!gridColumn for tabular data. Inputs write to variables through saveInto, which accepts a single saver or a list of savers so one action can update several targets.
Dynamic behaviour comes from local variables (a!localVariables), a!showWhen for conditional visibility, and a!refreshVariable to control when a computed value re-evaluates. Record types drive record views, record lists, and record actions, which typically reuse interfaces.
Traps
- Interfaces are stateless and cannot read process variables; pass everything through rule inputs.
- Inside a grid column the current row is
fv!row(andfv!rowIndex), notri!. - A button must sit in a button layout or it will not render properly.
saveIntoon a grid stores the whole array; check whether you need the row or the list.- Overusing refresh settings causes cascading re-evaluation and slow forms.
Worked example
A comment box that appears only when a checkbox is ticked:
a!textField(label: "Comment", value: ri!comment, saveInto: ri!comment, showWhen: ri!needsComment)
The field still exists in the expression and its value persists in the variable, so also validate on submit - hiding a field does not clear it.
Rule of thumb: data flows in through rule inputs, is held in local variables, and leaves through saveInto; design every interface along that line.