Clone on Gitea
Introduction
Explained by ducks
FAQ
Getting Started
Components
Component Basics
Auto Initialization From DOM
Templates
Children and Parents
Roles
Strictness
Fields
What is a Field
Binding Fields to DOM
Reading and Writing Fields
Value Casting
Flags
Events
Overview
Event Handlers
DOM Events
Custom Events
Propagation and Flow
Advanced Event Control
Beyond Components
States
Overview
StateEngine
DisplayStateEngine
Field Matchers
Ordering and priority
Debugging
Advanced usage
Ajax
ComponentUI
VirtualForm
Unit Testing
Helpers
Overview
Cookies
Arrays

Field matchers

So far we used simple equality checks like:

[ { status: "paid" }, ... ]

But in real applications you often need more expressive conditions. This is where field matchers come in. Field matchers let you express things like:

  • field is blank
  • field is present
  • field is one of a set of values
  • field is not in a set
  • or even some custom logic

All of this is still written inside the when part of a state rule.

Built-in matchers

Qite provides several built-in matchers that you can reference by name. You use them by writing a string that ends with (). Example:

[ { email: "isBlank()" },             ... ]
[ { tracking_number: "isPresent()" }, ... ]
[ { items: "isEmpty()" },             ... ]

These correspond to:

  • isBlank() –- true if value is null, undefined, or has length 0.
  • isPresent() –- true if value is not null or undefined.
  • isEmpty() –- true if value has length 0 (but not null).

You may find source code for matchers in the src/lib/states/matchers.js

Membership matchers and passing arguments

If you pass an array as a field value, Qite treats it as a membership test:

[ { status: ["draft", "submitted"] }, ... ]

This means status is either "draft" or "submitted". It is equivalent to calling an explicit in(), which this notation is basically translated into. The in() matcher accepts arguments as an array:

[ { status: ["in()", ["draft", "submitted"]] }, ... ]

This also demonstrates how matchers accept arguments — you can pass them by wrapping the matcher name and arguments in an array. The first element must be a matcher name ending in (). The remaining elements are passed as arguments to that matcher.

There's also a notIn() matcher:

[ { status: ["notIn()", ["cancelled", "refunded"]] }, ... ]

which, in this case, means status must not be "cancelled" or "refunded" in order for this state to activate.

Custom matcher functions

You can always have your own matcher by passing a function:

[ { total: (c,v) => value > 1000 }, ... ]

The matcher function receives:

  • c— the component instance
  • v— the current field value

and it must return true or false— that's how Qite's state engine decides whether matcher actually matched or not. You can also combine matchers freely:

[
    {
        fields: {
            status: ["draft", "submitted"],
            total: (c, v) => v > 1000
        },
        flags: ["!saving"]
    },
    ...
]

When is this evaluated?

Matchers are evaluated every time the engine recomputes active states. They are not cached. Each evaluation reads the current field and flag values. If a matcher throws (for example, because you used isEmpty() on a number), the error is not swallowed. It surfaces immediately so configuration mistakes are obvious.

Keep it readable

While matchers are powerful, avoid turning rules into mini programs. If your condition becomes complicated, consider extracting it into a clearly named function:

[ (c) => c.isEligibleForPriorityShipping(), ... ]

States are meant to make logic clearer, not harder to read. In the next section we will look at debugging state behavior and understanding why particular states are active.