Skip to Content
Docs@PortalField — UI fields

@PortalField — UI fields

Field or function-level annotation — declares an entity property as a UI field visible in the table, form, or filter panel.

@Target(AnnotationTarget.FIELD, AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) annotation class PortalField( val label: String, val labelKey: String = "", val tab: String = "", val renderer: RendererType = RendererType.AUTO, val order: Int = 0, val readonly: Boolean = false, val hidden: Boolean = false, val showInTable: Boolean = true, val showInFilter: Boolean = true, val required: Boolean = false, val placeholder: String = "", val tooltip: String = "", val tooltipKey: String = "", val width: Int = 0, val group: String = "", val displayExpression: String = "", val filterType: FilterType = FilterType.AUTO, val selectOptions: Array<String> = [], val selectEnum: KClass<*> = Unit::class, val min: Double = Double.NaN, val max: Double = Double.NaN, val defaultValue: String = "" )

selectEnum — when set, SELECT/MULTI_SELECT options are built by calling .toString() on each enum constant. If the enum does not override toString(), the constant’s name is used (e.g. "VIP"). The value in @PortalDependency must match the same toString() result.

Parameters

ParameterTypeDefaultDescription
labelStringColumn / form field label
labelKeyString""i18n key for label
tabString""PortalTab enum constant name (e.g. "BASIC")
rendererRendererTypeAUTOUI component type
orderInt0Sort position within tab / group
readonlyBooleanfalseAlways read-only, even in edit mode
hiddenBooleanfalseExcluded from table and form
showInTableBooleantrueWhether to show as a table column
showInFilterBooleantrueWhether to show in the filter panel
requiredBooleanfalseMust be non-empty before saving
placeholderString""Placeholder text for input
tooltipString""Short help text near the field
tooltipKeyString""i18n key for tooltip
widthInt0Preferred column width in px (0 = auto)
groupString""Visually groups related fields within a tab
displayExpressionString""Template ${fieldName} for computed display values
filterTypeFilterTypeAUTOFilter strategy
selectOptionsArray<String>[]Explicit options for SELECT/MULTI_SELECT
selectEnumKClass<*>Unit::classEnum whose constants define options
minDoubleNaNMinimum value for NUMBER/DECIMAL
maxDoubleNaNMaximum value for NUMBER/DECIMAL
defaultValueString""Default value when creating a new record

RendererType — renderer types

ValueDescriptionNotes
AUTOFramework infers from JPA/Kotlin typeDefault
TEXTSingle-line text input
TEXTAREAMulti-line text areaUse @Column(columnDefinition = "TEXT")
NUMBERInteger numeric inputInt, Long
DECIMALFloating-point inputDouble, BigDecimal
DATEDate picker (ISO-8601 YYYY-MM-DD)
DATETIMEDate and time picker (YYYY-MM-DDTHH:mm)
BOOLEANCheckbox / toggleBoolean
SELECTSingle-value dropdownRequires selectOptions or selectEnum
MULTI_SELECTMulti-value dropdownComma-separated in the database
RELATIONManyToOne / OneToOne pickerRequires @PortalRelation + @PortalLookup
RELATION_LISTOneToMany / ManyToMany inline listRequires @PortalRelation + @PortalLookup
PASSWORDPassword input (masked)Not shown in table
EMAILEmail with format validation
URLURL with format validation
COLORColor picker (hex #FF5733)length = 7
FILEFile / image uploadPath or base64
JSONRaw JSON editor@Column(columnDefinition = "TEXT")
CUSTOMCustom renderer from frontend

FilterType — filter strategies

ValueDescriptionExample SQL
AUTOInferred from field type
EXACTEquality matchfield = :value
CONTAINSCase-insensitive substringLOWER(field) LIKE %value%
STARTS_WITHPrefix searchLOWER(field) LIKE value%
RANGENumeric or date rangefield BETWEEN :from AND :to
INValue-set membershipfield IN (:values)
BOOLEANBoolean equalityfield = true/false
NONENot filterable

Examples

Text field with validation:

@Column(length = 100, nullable = false) @PortalField( label = "Full Name", tab = "BASIC", order = 1, required = true, renderer = RendererType.TEXT, filterType = FilterType.CONTAINS, placeholder = "Enter full name" ) var name: String = ""

SELECT field with enum:

enum class Status { ACTIVE, INACTIVE, PENDING } @Column(length = 20) @Enumerated(EnumType.STRING) @PortalField( label = "Status", order = 2, renderer = RendererType.SELECT, filterType = FilterType.IN, selectEnum = Status::class ) var status: Status? = null

SELECT field with options list:

@Column(length = 20) @PortalField( label = "Priority", order = 3, renderer = RendererType.SELECT, filterType = FilterType.IN, selectOptions = ["LOW", "MEDIUM", "HIGH", "CRITICAL"] ) var priority: String = ""

DECIMAL field with range:

@Column @PortalField( label = "Price", order = 5, renderer = RendererType.DECIMAL, filterType = FilterType.RANGE, min = 0.0, max = 99999.99, placeholder = "0.00" ) var price: Double = 0.0

DATE field:

@Column @PortalField( label = "Birth Date", order = 6, renderer = RendererType.DATE, filterType = FilterType.RANGE, showInTable = false, tooltip = "Format: YYYY-MM-DD" ) var birthDate: String = ""

Read-only ID field:

@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @PortalField(label = "ID", order = 0, readonly = true, showInFilter = false) var id: Long = 0

Field with displayExpression:

@PortalField( label = "Full Name", order = 7, displayExpression = "\${firstName} \${lastName}", showInTable = true, readonly = true ) var fullName: String = ""

Field with default value:

@Column @PortalField( label = "Active", order = 8, renderer = RendererType.BOOLEAN, defaultValue = "true" ) var isActive: Boolean = true

@Regex — pattern validation

Field-level annotation that attaches a regex propagated to the frontend as client-side validation.

annotation class Regex( val pattern: String, val message: String = "The value does not match the required format" )
@Column(length = 20) @Regex( pattern = """^\+?[\d\s\-]{7,20}$""", message = "Phone number may contain digits, spaces, hyphens, and an optional +" ) @PortalField(label = "Phone", order = 2, renderer = RendererType.TEXT) var phone: String = ""

@Regex is client-side only. Add backend validation separately (e.g. Bean Validation @Pattern).

Last updated on