Forms & Editors
Forms in Serenity are defined declaratively with a form class — a plain class whose properties describe the fields of an edit dialog. Each property becomes a form field, and the editor used for it is determined by attributes on the property (or inherited from the row via [BasedOnRow]).
The Form Class
A form class is a plain class with public properties. Each property becomes a form field:
[FormScript]
public class OrderForm
{
[DisplayName("Customer"), LookupEditor(typeof(CustomerRow))]
public string CustomerID { get; set; }
[TextAreaEditor(Rows = 3)]
public string Description { get; set; }
[HalfWidth]
public DateTime? OrderDate { get; set; }
}
The [FormScript] attribute marks the class so that a form script is generated (see Script Generation). Like columns, a form script is a PropertyItemsScript that produces a PropertyItemsData JSON structure, loaded on the client with getFormDataAsync("Key").
[BasedOnRow]
Just like columns, a form class is usually based on a row. The BasedOnRowAttribute makes each form property inherit the attributes from the matching row field (editor type, required, insertable/updatable, etc.):
[FormScript("Northwind.Order")]
[BasedOnRow(typeof(OrderRow))]
public class OrderForm
{
[HalfWidth]
public string CustomerID { get; set; }
// ...
}
- Properties whose names match row fields inherit the row field's attributes.
CheckNames = truevalidates that every property matches a row field (add[SkipNameCheck]to properties that shouldn't be checked).
Editor Attributes
The editor for a field is set with an editor attribute. Serenity ships a large set of built-in editor attributes (in the Serenity.ComponentModel namespace), including:
| Editor | Attribute | Typical use |
|---|---|---|
| String | [StringEditor] |
Single-line text |
| TextArea | [TextAreaEditor] |
Multi-line text |
| Boolean | [BooleanEditor] |
Checkbox |
| Integer / Decimal | [IntegerEditor] / [DecimalEditor] |
Numeric input |
| Date / DateTime | [DateEditor] / [DateTimeEditor] |
Date/time pickers |
| Enum | [EnumEditor] |
Dropdown from an enum |
| Lookup | LookupEditorAttribute | Dropdown from a lookup script |
| ServiceLookup | [ServiceLookupEditor] |
Dropdown from a service lookup |
| Password | [PasswordEditor] |
Password input |
| Email / Url | [EmailAddressEditor] / [URLEditor] |
Email/URL input |
| HtmlContent | [HtmlContentEditor] |
Rich HTML editor |
| Time | [TimeEditor] |
Time picker |
How Editor Attributes Work
All editor attributes derive from CustomEditorAttribute, which in turn derives from EditorTypeAttribute. EditorTypeAttribute sets the editor type key (e.g. "Lookup", "Date"), and CustomEditorAttribute adds the ability to set editor options:
public abstract class CustomEditorAttribute(string editorType) : EditorTypeAttribute(editorType)
{
protected void SetOption(string key, object? value);
protected TType GetOption<TType>(string key);
}
The options set via SetOption are transferred to the editorParams dictionary of the generated PropertyItem, which the client editor reads.
[EditorOption]
EditorOptionAttribute lets you set an arbitrary editor option directly on a property:
[EditorOption("minValue", 0), EditorOption("maxValue", 100)]
public int? Score { get; set; }
Avoid this where possible — option keys and values are not checked. Prefer a typed editor attribute (e.g.
[IntegerEditor(MinValue = 0, MaxValue = 100)]) which is validated.
[EditorCssClass]
EditorCssClassAttribute adds a CSS class to the editor element itself (as opposed to [CssClass], which targets the field container).
Form Field Attributes
These attributes control how a form field behaves and is laid out.
Validation & Editing
| Attribute | PropertyItem property |
Description |
|---|---|---|
| RequiredAttribute | required |
Marks the field as required |
| MaxLengthAttribute | maxLength |
Maximum input length |
| OneWayAttribute | oneWay |
Value is sent to server but not loaded back |
InsertableAttribute / [Updatable] |
insertable / updatable |
Editable on new/edit record mode |
HideOnInsertAttribute / [HideOnUpdate] |
visible |
Hidden on new/edit record mode |
Layout & Grouping
| Attribute | PropertyItem property |
Description |
|---|---|---|
| TabAttribute | category |
Places the field in a tab/category |
| CollapsibleAttribute | collapsible |
Makes the field's category collapsible |
| SortOrderAttribute | sortOrder |
Field order within the form |
| GroupOrderAttribute | groupOrder |
Order of the field's group |
| ResizableAttribute | resizable |
Allows resizing the field |
| UnboundAttribute | unbound |
Field is not bound to a row field |
| SkipNameCheckAttribute | — | Skips CheckNames validation for this property |
Width & Layout
Form field widths are set with the layout width attributes, which apply Bootstrap grid column classes:
| Attribute | CSS class | Width |
|---|---|---|
| FullWidthAttribute | col-sm-12 |
Full row |
| HalfWidthAttribute | col-sm-6 |
Half row |
OneThirdWidthAttribute |
col-sm-4 |
One third |
TwoThirdWidthAttribute |
col-sm-8 |
Two thirds |
QuarterWidthAttribute |
col-sm-3 |
Quarter |
ThreeQuarterWidthAttribute |
col-sm-9 |
Three quarters |
All of these derive from FormWidthAttribute, which lets you set responsive widths per device size (XSmall, Small, Medium, Large) and control whether the width applies to the current field only (JustThis) or to all following fields (UntilNext).
Editor Add-ons
EditorAddonAttribute adds an editor add-on to a field — a small UI element attached to the editor (e.g. a button or icon). It's AllowMultiple, so a field can have several add-ons:
[EditorAddon("MyAddon", Option = "value")]
public string SomeField { get; set; }
The add-on type and its options are transferred to the PropertyItem's editorAddons collection (see EditorAddonItem).