Skip to content

Rules

Rules define reactive browser-side behavior that runs automatically when form state changes.

Implement RuleSupplier and return a list of Rule objects from rules(). Mateu evaluates them in the browser whenever any field value changes.


@Route(value = "/my-page", parentRoute = "")
public class MyPage implements ComponentTreeSupplier, RuleSupplier {
@Override
public Form component(HttpRequest httpRequest) { ... }
@Override
public List<Rule> rules() {
return List.of(
Rule.builder()
.filter("true") // when to run
.action(RuleAction.SetDataValue)
.fieldName("myField") // target component id
.fieldAttribute(RuleFieldAttribute.hidden)
.expression("!state.show") // computed value
.result(RuleResult.Continue) // keep evaluating other rules
.build()
);
}
}

Each rule has:

  • filter — a JS expression; the rule only runs if this evaluates to truthy
  • action — what to do
  • fieldName — the component(s) to target (comma-separated for multiple)
  • expression or value — the new value to apply
  • resultContinue (keep evaluating) or Stop (stop after this rule)

Show or hide a component based on state.

Rule.builder()
.filter("true")
.action(RuleAction.SetDataValue)
.fieldName("texto")
.fieldAttribute(RuleFieldAttribute.hidden)
.expression("state.hidden") // true = hidden, false = visible
.result(RuleResult.Continue)
.build()

The target component needs an id:

Text.builder()
.id("texto")
.text("Now you see me")
.build()

Enable or disable a component based on state.

Rule.builder()
.filter("true")
.action(RuleAction.SetDataValue)
.fieldName("aButton,aField") // multiple targets
.fieldAttribute(RuleFieldAttribute.disabled)
.expression("!state.enable") // true = disabled
.result(RuleResult.Continue)
.build()

Toggle enabled/disabled state from an action return value using Data:

boolean buttonDisabled = false;
boolean fieldDisabled = false;
Form component = Form.builder()
.content(List.of(
new Button("A Button"),
FormField.builder().id("aField")...build(),
new Button("Toggle", () ->
new Data(
Map.of(
"aButton.disabled", buttonDisabled = !buttonDisabled,
"aField.disabled", fieldDisabled = !fieldDisabled
),
this))
))
.build();

Data(Map, state) updates specific component attributes directly without a Rule.

Similarly, use "componentId.hidden" to toggle visibility from the backend.


Apply inline CSS to a component based on state.

// When trigger is checked → blue border
Rule.builder()
.filter("state.trigger")
.action(RuleAction.SetStyle)
.fieldName("text")
.expression("border") // CSS property name
.value("3px solid blue") // CSS value
.result(RuleResult.Continue)
.build(),
// When trigger is unchecked → red border
Rule.builder()
.filter("!state.trigger")
.action(RuleAction.SetStyle)
.fieldName("text")
.expression("border")
.value("3px solid red")
.result(RuleResult.Continue)
.build()

Add or remove CSS classes based on state.

Rule.builder()
.filter("state.trigger")
.action(RuleAction.SetCssClass)
.fieldName("text")
.value("red-theme") // CSS class name
.result(RuleResult.Continue)
.build(),
Rule.builder()
.filter("!state.trigger")
.action(RuleAction.SetCssClass)
.fieldName("text")
.value("blue-theme")
.result(RuleResult.Continue)
.build()

Set any HTML attribute on a component.

Rule.builder()
.filter("state.trigger")
.action(RuleAction.SetAttributeValue)
.fieldAttribute(RuleFieldAttribute.style)
.fieldName("text")
.value("border: 3px solid blue;")
.result(RuleResult.Continue)
.build()

Write a computed value to the data context. Useful for derived values accessible via ${data.field}.

Rule.builder()
.filter("true")
.action(RuleAction.SetDataValue)
.fieldAttribute(RuleFieldAttribute.none)
.fieldName("calculated")
.expression("state.trigger") // compute from state
.result(RuleResult.Continue)
.build()

Read the value in a component:

new Text("${JSON.stringify(data)}")

Trigger a backend action automatically when a condition is met.

Rule.builder()
.filter("true")
.action(RuleAction.RunAction)
.actionId("action_id")
.result(RuleResult.Continue)
.build()

The page must also implement ActionHandler to handle "action_id".


Execute JavaScript in the browser when a condition is met.

Rule.builder()
.filter("true")
.action(RuleAction.RunJS)
.value("console.log('hola!', state, data, appState, appData);")
.result(RuleResult.Continue)
.build()

The JS runs with state, data, appState, and appData in scope.


RuleActionEffect
SetDataValueSet a field attribute (hidden, disabled) or data value
SetStyleSet a CSS property on a component
SetCssClassSet CSS classes on a component
SetAttributeValueSet any HTML attribute on a component
RunActionTrigger a declared action
RunJSRun JavaScript in the browser
RuleFieldAttributeControls
hiddenVisibility of the component
disabledEnabled/disabled state
styleInline CSS style string
noneUsed when writing to data context