@PortalDependency — conditional rules
Field-level annotation (repeatable) — defines conditional rules controlling field visibility, available options, and numeric range based on other form field values.
@Target(AnnotationTarget.FIELD, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@Repeatable
annotation class PortalDependency(
val field: String = "",
val operator: DependencyOperator = DependencyOperator.UNSPECIFIED,
val value: String = "",
val values: Array<String> = [],
val condition: String = "",
val visibility: DependencyVisibility = DependencyVisibility.NONE,
val allowedValues: Array<String> = [],
val min: String = "",
val max: String = "",
val message: String = "",
val clearOnHide: Boolean = true
)Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
field | String | "" | Name of the field this rule depends on |
operator | DependencyOperator | UNSPECIFIED | Comparison operator |
value | String | "" | Value to compare (single) |
values | Array<String> | [] | Value set for IN / NOT_IN |
condition | String | "" | Complex condition as JSON AST (allOf/anyOf/not) |
visibility | DependencyVisibility | NONE | SHOW, HIDE, or NONE |
allowedValues | Array<String> | [] | Restricts SELECT options to this list |
min | String | "" | Min numeric value; a number ("10") or field ref ("$creditLimit") |
max | String | "" | Max numeric value; a number or field ref |
message | String | "" | Message shown when the rule is active |
clearOnHide | Boolean | true | Whether to clear field value when it becomes hidden |
DependencyVisibility
| Value | Description |
|---|---|
NONE | Rule does not affect visibility — only restricts values or range |
SHOW | Field is visible only when condition is met |
HIDE | Field is hidden when condition is met |
DependencyOperator
| Value | Description |
|---|---|
UNSPECIFIED | No operator — use when condition is a JSON string in condition |
EQ | Equality |
NEQ | Inequality |
IN | Value in set |
NOT_IN | Value not in set |
CONTAINS | Contains substring |
NOT_CONTAINS | Does not contain substring |
IS_EMPTY | Value is empty |
IS_NOT_EMPTY | Value is not empty |
GT / GTE / LT / LTE | Numeric comparisons |
Examples
Conditional visibility (SHOW):
@Column
@PortalField(label = "VIP Discount (%)", order = 5, renderer = RendererType.DECIMAL)
@PortalDependency(
field = "customerType",
operator = DependencyOperator.EQ,
value = "VIP",
visibility = DependencyVisibility.SHOW,
message = "VIP discount available only for VIP customers"
)
var vipDiscount: Double = 0.0Conditional visibility (HIDE):
@Column
@PortalField(label = "Cancellation Reason", order = 8, renderer = RendererType.TEXTAREA)
@PortalDependency(
field = "status",
operator = DependencyOperator.NEQ,
value = "CANCELLED",
visibility = DependencyVisibility.HIDE
)
var cancellationReason: String = ""Restricting available options:
@Column
@PortalField(label = "Tags", order = 4, renderer = RendererType.MULTI_SELECT, selectEnum = Tag::class)
@PortalDependency(
field = "customerType",
operator = DependencyOperator.EQ,
value = "New",
allowedValues = ["NEW"],
message = "New customers can only have the NEW tag"
)
@PortalDependency(
field = "customerType",
operator = DependencyOperator.EQ,
value = "Premium",
allowedValues = ["PREMIUM", "REGULAR", "NEW"]
)
var tags: String = ""Numeric range constraint:
@Column
@PortalField(label = "Credit Limit", order = 3, renderer = RendererType.DECIMAL)
@PortalDependency(
field = "customerType",
operator = DependencyOperator.EQ,
value = "New",
max = "5000",
message = "New customer — max 5000"
)
@PortalDependency(
field = "customerType",
operator = DependencyOperator.EQ,
value = "VIP",
min = "5000", max = "500000"
)
var creditLimit: Double = 0.0Field reference in range ($ prefix):
@Column
@PortalField(label = "Sale Price", order = 5, renderer = RendererType.DECIMAL)
@PortalDependency(
field = "isDiscounted",
operator = DependencyOperator.EQ,
value = "true",
max = "\$listPrice" // max = value of the listPrice field
)
var salePrice: Double = 0.0Complex JSON condition (anyOf/allOf):
@Column
@PortalField(label = "Special Field", order = 9, renderer = RendererType.TEXT)
@PortalDependency(
condition = """
{
"anyOf": [
{"field": "customerType", "operator": "eq", "value": "VIP"},
{
"allOf": [
{"field": "isActive", "operator": "eq", "value": "true"},
{"field": "loyaltyPoints", "operator": "gte", "value": "1000"}
]
}
]
}
""",
visibility = DependencyVisibility.SHOW
)
var specialField: String = ""IN operator (multiple values):
@Column
@PortalField(label = "Priority Service", order = 10, renderer = RendererType.BOOLEAN)
@PortalDependency(
field = "customerType",
operator = DependencyOperator.IN,
values = ["VIP", "PREMIUM", "BUSINESS"],
visibility = DependencyVisibility.SHOW
)
var priorityService: Boolean = falseLast updated on