RulesField
Form field component for building conditional rule rows with customizable placeholders, actions, and optional row reordering.
Component
Build rule conditions to filter results
Props
| Props | Required | Default | Type |
|---|---|---|---|
id | true | — | string |
label | — | — | string |
itemFieldAriaLabel | — | 'Rule item' | string |
operatorFieldAriaLabel | — | 'Rule operator' | string |
valueFieldAriaLabel | — | 'Rule value' | string |
addRuleAriaLabel | — | 'Add rule' | string |
removeRuleAriaLabel | — | 'Remove rule' | string |
sortingType | — | RepeatingFieldSortingType.NONE | RepeatingFieldSortingType |
moveUpAriaLabel | — | 'Move rule up' | string |
moveDownAriaLabel | — | 'Move rule down' | string |
dragHandleAriaLabel | — | 'Drag to reorder rule' | string |
moveUpIcon | — | 'mdi:arrow-up' | string |
moveDownIcon | — | 'mdi:arrow-down' | string |
dragHandleIcon | — | 'mdi:drag-vertical' | string |
dragPlaceholderText | — | 'Drop here' | string |
showDragPlaceholderText | — | true | boolean |
dragPlaceholderClass | — | — | string |
dragPlaceholderTextClass | — | — | string |
helpText | — | — | string |
helpTextPosition | — | Position.BOTTOM | Position |
itemOptions | — | [] | SelectOption[] |
operatorOptions | — | [] | SelectOption[] |
modelValue | — | [] | RuleItem[] |
itemPlaceholder | — | 'Select item' | string |
operatorPlaceholder | — | 'Select operator' | string |
valuePlaceholder | — | 'Enter value' | string |
addIcon | — | 'mdi:plus-circle-outline' | string |
removeIcon | — | 'mdi:minus-circle-outline' | string |
mobileBtnAddText | — | 'Add rule' | string |
mobileBtnRemoveText | — | 'Remove rule' | string |
validator | — | — | Function |
maxRules | — | — | number |
error | — | '' | string |
disabled | — | false | boolean |
required | — | false | boolean |
showOptionalLabel | — | true | boolean |
optionalLabel | — | — | string |
transparentInputs | — | false | boolean |
Usage
id
Sets the id prefix used internally by each row input (item, operator, value, action).
<template>
<RulesField id="rules-field-id" />
</template>
label
Sets the field label displayed above the rules rows.
<template>
<RulesField
id="rules"
label="Rules"
/>
</template>
itemFieldAriaLabel
Sets the base accessible label for the item select of each row.
<template>
<RulesField
id="rules"
itemFieldAriaLabel="Filter field"
/>
</template>
operatorFieldAriaLabel
Sets the base accessible label for the operator select of each row.
<template>
<RulesField
id="rules"
operatorFieldAriaLabel="Filter operator"
/>
</template>
valueFieldAriaLabel
Sets the base accessible label for the value input of each row.
<template>
<RulesField
id="rules"
valueFieldAriaLabel="Filter value"
/>
</template>
addRuleAriaLabel
Sets the accessible label for the add-rule icon button.
<template>
<RulesField
id="rules"
addRuleAriaLabel="Add condition"
/>
</template>
removeRuleAriaLabel
Sets the accessible label for the remove-rule icon button.
<template>
<RulesField
id="rules"
removeRuleAriaLabel="Remove condition"
/>
</template>
sortingType
Controls how users can reorder rules. none disables reordering, buttons shows up/down icon buttons in each row's action column, and drag shows a drag handle for native drag-and-drop reordering with a dashed placeholder marking the drop position. The drag handle is desktop-only; on mobile, drag mode falls back to the same up/down buttons as buttons mode. It uses the RepeatingFieldSortingType enum.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.BUTTONS"
/>
</template>
Options
| Value | Description |
|---|---|
NONE | none |
BUTTONS | buttons |
DRAG | drag |
moveUpAriaLabel
Sets the accessible label for the move-rule-up icon button, shown when sortingType is buttons.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.BUTTONS"
moveUpAriaLabel="Move condition up"
/>
</template>
moveDownAriaLabel
Sets the accessible label for the move-rule-down icon button, shown when sortingType is buttons.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.BUTTONS"
moveDownAriaLabel="Move condition down"
/>
</template>
dragHandleAriaLabel
Sets the accessible label for the drag handle, shown when sortingType is drag.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.DRAG"
dragHandleAriaLabel="Drag to reorder condition"
/>
</template>
moveUpIcon
Sets the icon used on the move-rule-up button.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.BUTTONS"
moveUpIcon="mdi:chevron-up"
/>
</template>
moveDownIcon
Sets the icon used on the move-rule-down button.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.BUTTONS"
moveDownIcon="mdi:chevron-down"
/>
</template>
dragHandleIcon
Sets the icon used on the drag handle.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.DRAG"
dragHandleIcon="mdi:dots-grid"
/>
</template>
dragPlaceholderText
Sets the text passed to the underlying DragPlaceholder's text prop, shown in the dashed drop-position placeholder when showDragPlaceholderText is true.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.DRAG"
dragPlaceholderText="Drop rule here"
/>
</template>
showDragPlaceholderText
Sets the DragPlaceholder's showText prop, controlling whether dragPlaceholderText is rendered inside the drop-position placeholder shown when sortingType is drag.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.DRAG"
:showDragPlaceholderText="true"
/>
</template>
dragPlaceholderClass
Sets the class applied to the DragPlaceholder's root element, letting you override its default border, background, or spacing.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.DRAG"
dragPlaceholderClass="border-border-primary-brand-default"
/>
</template>
dragPlaceholderTextClass
Sets the DragPlaceholder's textClass prop, letting you override the default styling of dragPlaceholderText when showDragPlaceholderText is true.
<template>
<RulesField
id="rules"
:sortingType="RepeatingFieldSortingType.DRAG"
:showDragPlaceholderText="true"
dragPlaceholderTextClass="text-sm font-semibold"
/>
</template>
helpText
Shows helper text below the field when there is no error.
<template>
<RulesField
id="rules"
helpText="Build one or more conditions to filter records"
/>
</template>
helpTextPosition
Sets the position of the help text relative to the field. It uses the Position enum.
<template>
<RulesField
id="rules"
:helpTextPosition="Position.TOP"
helpText="Appears above the field"
/>
</template>
Options
| Value | Description |
|---|---|
TOP | top |
BOTTOM | bottom |
itemOptions
Defines the available options for the first select in each row (the "item" column).
<template>
<RulesField
id="rules"
:itemOptions="itemOptions"
/>
</template>
<script setup lang="ts">
const itemOptions = [
{
value: 'status',
text: 'Status',
},
{
value: 'age',
text: 'Age',
},
]
</script>
operatorOptions
Defines the available options for the operator select in each row. You can optionally use applicableTypes to conditionally display operators based on the selected item's input type.
<template>
<RulesField
id="rules"
:operatorOptions="operatorOptions"
/>
</template>
<script setup lang="ts">
const operatorOptions = [
{
value: 'eq',
text: 'Equals',
applicableTypes: ['text', 'number', 'date', 'email', 'tel'],
},
{
value: 'contains',
text: 'Contains',
applicableTypes: ['text', 'email', 'tel', 'url'],
},
{
value: 'gt',
text: 'Greater than',
applicableTypes: ['number', 'date'],
},
{
value: 'lt',
text: 'Less than',
applicableTypes: ['number', 'date'],
},
]
</script>
When applicableTypes is set on an operator, only operators matching the selected item's input type will be displayed. For example, "Greater than" will only show when you select a number or date field.
modelValue
Controls all rows in the rules field via v-model. Each row is represented by a RuleItem.
<template>
<RulesField
id="rules"
:itemOptions="itemOptions"
:operatorOptions="operatorOptions"
v-model="rules"
/>
</template>
<script setup lang="ts">
const rules = ref([
{ item: 'status', operator: 'eq', value: 'active', type: 'text' },
{ item: 'age', operator: 'gt', value: 21, type: 'number' },
])
</script>
TypeScript type and interface
type RuleValue = string | number | null
interface RuleItem {
item: RuleValue
operator: RuleValue
value: RuleValue
type?: AllowedInputType
}
type is forwarded to each row InputField type prop, so rows can use different input types.
<script setup lang="ts">
const rules = ref([
{ item: 'status', operator: 'eq', value: 'active', type: 'text' },
{ item: 'age', operator: 'gt', value: 21, type: 'number' },
{ item: 'startDate', operator: 'eq', value: '2026-03-18', type: 'date' },
])
</script>
itemPlaceholder
Sets placeholder text for the item select in each row.
<template>
<RulesField
id="rules"
itemPlaceholder="Choose a field"
/>
</template>
operatorPlaceholder
Sets placeholder text for the operator select in each row.
<template>
<RulesField
id="rules"
operatorPlaceholder="Choose a condition"
/>
</template>
valuePlaceholder
Sets placeholder text for the value input in each row.
<template>
<RulesField
id="rules"
valuePlaceholder="Type comparison value"
/>
</template>
addIcon
Sets the icon used on the add-action button for the last row.
<template>
<RulesField
id="rules"
addIcon="mdi:plus"
/>
</template>
removeIcon
Sets the icon used on remove-action buttons for non-last rows.
<template>
<RulesField
id="rules"
removeIcon="mdi:minus"
/>
</template>
mobileBtnAddText
Sets the add button text shown on mobile rows.
<template>
<RulesField
id="rules"
mobileBtnAddText="Add condition"
/>
</template>
mobileBtnRemoveText
Sets the remove button text shown on mobile rows.
<template>
<RulesField
id="rules"
mobileBtnRemoveText="Remove condition"
/>
</template>
validator
Validation callback for the whole rules array. Used together with required and v-model:error.
<template>
<RulesField
id="rules"
:itemOptions="itemOptions"
:operatorOptions="operatorOptions"
v-model="rules"
v-model:error="errorMessage"
:required="true"
:validator="validateRules"
/>
</template>
maxRules
Sets the maximum number of rules users can add in the UI. When the limit is reached, the add action is disabled.
<template>
<RulesField
id="rules"
:itemOptions="itemOptions"
:operatorOptions="operatorOptions"
v-model="rules"
:maxRules="10"
/>
</template>
error (v-model:error)
Displays error text below the field and applies error styling to the label.
<template>
<RulesField
id="rules"
:itemOptions="itemOptions"
:operatorOptions="operatorOptions"
v-model="rules"
v-model:error="errorMessage"
/>
</template>
disabled
Disables all row controls and action buttons.
<template>
<RulesField
id="rules"
:itemOptions="itemOptions"
:operatorOptions="operatorOptions"
v-model="rules"
disabled
/>
</template>
required
Enables validation execution together with validator.
<template>
<RulesField
id="rules"
:itemOptions="itemOptions"
:operatorOptions="operatorOptions"
v-model="rules"
:required="true"
:validator="validateRules"
/>
</template>
showOptionalLabel
When the field is not required, shows an "(optional)" hint next to the label. Set to false to hide it. The hint text defaults to a global setting that can be overridden project-wide, and can also be overridden per field with the optionalLabel prop.
<template>
<RulesField label="Rules" :showOptionalLabel="false" />
</template>
optionalLabel
Overrides the "(optional)" hint text for this specific field, taking priority over the global default.
<template>
<RulesField label="Rules" optionalLabel="(not required)" />
</template>
transparentInputs
When true, passes transparent to all child SelectField and InputField components in each row, removing their default background.
<template>
<RulesField
id="rules"
transparentInputs
/>
</template>
Full example
<template>
<Form @submit="handleSubmit">
<FormRow>
<RulesField
id="customer-rules"
label="Customer filters"
helpText="Add one or more conditions"
:itemOptions="itemOptions"
:operatorOptions="operatorOptions"
v-model="formData.rules"
v-model:error="formErrors.rules"
itemPlaceholder="Select field"
operatorPlaceholder="Select operator"
valuePlaceholder="Enter value"
addIcon="mdi:plus-circle-outline"
removeIcon="mdi:minus-circle-outline"
mobileBtnAddText="Add condition"
mobileBtnRemoveText="Remove condition"
:sortingType="RepeatingFieldSortingType.BUTTONS"
moveUpAriaLabel="Move condition up"
moveDownAriaLabel="Move condition down"
:maxRules="10"
:required="true"
:validator="validateRules"
/>
</FormRow>
<FormActions>
<ActionButton
type="submit"
text="Apply rules"
:styleType="ButtonStyleType.PRIMARY_BRAND_FILLED"
/>
</FormActions>
</Form>
</template>
<script setup lang="ts">
const { $toast } = useNuxtApp()
const itemOptions = [
{
value: 'name',
text: 'Name',
inputType: 'text',
},
{
value: 'age',
text: 'Age',
inputType: 'number',
},
{
value: 'startDate',
text: 'Start date',
inputType: 'date',
},
]
const operatorOptions = [
{
value: 'eq',
text: 'Equals',
applicableTypes: ['text', 'number', 'date'],
},
{
value: 'contains',
text: 'Contains',
applicableTypes: ['text'],
},
{
value: 'gt',
text: 'Greater than',
applicableTypes: ['number', 'date'],
},
{
value: 'lt',
text: 'Less than',
applicableTypes: ['number', 'date'],
},
]
const formData = reactive({
rules: [
{
item: 'name',
operator: 'contains',
value: 'Ana',
type: 'text',
},
],
})
const validateRules = createRulesFieldValidator({
required: true,
maxRules: 10,
requiredFieldMessage: 'Add at least one complete rule.',
incompleteRuleMessage: 'Complete all rule fields before continuing.',
maxRulesMessage: 'You can add up to 10 rules.',
})
const { formErrors, resetForm, validateFormFields } = useForm({
formData,
requiredFields: ['rules'],
validators: {
rules: validateRules,
},
})
const handleSubmit = () => {
const isValid = validateFormFields()
if (!isValid) {
$toast.error('Some fields contain errors', {
toastId: 'rules-form-error',
})
return
}
$toast.success('Rules submitted successfully', {
toastId: 'rules-form-success',
})
resetForm()
}
</script>