Skip to main content
Version: v7 / v8

ValueEditor

Refer to the TypeScript reference page for information about the types and interfaces referenced below.

ValueEditor renders an <input> by default, or a <select> (by way of ValueSelector) if the value should be selected from a list. The useValueEditor Hook is called to massage the value if necessary and retrieve utilities for managing list values.

note

While React Query Builder does not restrict the rule value property to JavaScript primitives, every effort is made to keep the query object serializable. This means that editors that generate non-serializable values (like some date pickers) will store the value as a string, parsing it back into the required non-primitive type during the render process. Editors that allow or require multiple values (when operator is "between" or "in", for example) will typically store values as comma-separated strings.

Showcase

ValueEditor may be the default component most commonly overridden with a custom component (more information here), but it is capable of handling many common scenarios without customization. The query builder below demonstrates each of the supported options for the Field#valueEditorType and Field#inputType properties.

Rules 10 and 11 demonstrate the behavior when the operator is "between". Rule 12 demonstrates the behavior when a field's valueSources property is set to ["field", "value"].

note

This query builder has been specially configured in the following ways:

  1. The index (plus one) of the rule in the rules array is displayed to the left of the field selector.
  2. The value actually stored in the rule object within the query is displayed to the right of each value editor.
  3. To focus attention on the value editor components, all other components have been disabled or hidden.

1.
 (stored value: "")
2.
 (stored value: "option2")
3.
 (stored value: true)
4.
 (stored value: "option2")
5.
 (stored value: "")
6.
 (stored value: "option1,option2")
7.
 (stored value: "")
8.
 (stored value: "")
9.
 (stored value: "")
10.
 (stored value: "A,Z")
11.
 (stored value: "option2,option4")
12.
 (stored value: "text")
tip

The compatibility packages also implement these options using appropriate components from their respective style libraries (see the demo).

Value sources

By default, React Query Builder facilitates the comparison of fields (typically corresponding to database column names) to values (strings, numbers, etc.). But some situations call for comparisons between two fields. Consider this SQL statement:

SELECT *
FROM users
WHERE lastName LIKE firstName || '%';

That would return records where the user's last name began with the same letters as their first name and ended with any number of other characters (including zero). "Kris Kristofferson" would meet this criteria.

To represent that WHERE clause in React Query Builder, we can use the getValueSources prop or the valueSources property of the lastName field in the fields prop. When either of those evaluates to an array containing "field", and the valueSource property of the rule is set to "field", the <ValueEditor /> component will display a drop-down list of fields instead of values.

Example

In the query builder above, the definition for the field used in the last rule is:

{
"name": "field",
"label": "field",
"valueSources": ["field", "value"]
}

And the defaultQuery prop looks like this:

{
"combinator": "and",
"rules": [
// ...other rules...
{ "field": "field", "operator": "=", "value": "text", "valueSource": "field" }
]
}

Since the field's valueSources property is an array with length > 1, a "value source selector" component is displayed to the left of the <ValueEditor />.

tip

To reorder the rule components, for example to move the value source selector to the right of the value editor, you can use the CSS Flexbox order property).

note

The Field#valueSources property can also be a function that takes an operator name as its only parameter and returns the required array.

Filtering the field list

Not all fields will be compatible with each other, so each field may provide a comparator property specifying which fields show up in the value editor list. If comparator is a string, then only fields which have the same value as the current field in the property matching the comparator string will be listed.

That's a mouthful, so let's look at an example. In the following field list, fields f1, f2, and f3 share a common property datatype: "number". f1 identifies the datatype property as its comparator. Therefore, when a rule specifies the field f1, only f2 and f3 will be in the drop-down list because their datatype property matches f1's. f4 and f5 will be excluded because their datatype property does not match f1's, and f1 will be excluded because a rule's selected field cannot be compared with itself.

const fields: Field[] = {
{
name: 'f1',
label: 'f1',
valueSources: ["field"],
comparator: 'datatype',
datatype: 'number'
},
{ name: 'f2', label: 'f2', datatype: 'number' },
{ name: 'f3', label: 'f3', datatype: 'number' },
{ name: 'f4', label: 'f4', datatype: 'string' },
{ name: 'f5', label: 'f5', datatype: 'string' },
}

The comparator property can also be a function that takes a Field object as its only parameter. Each field in the fields prop will be evaluated by this function. It should return true if the field should be included in the list, and false otherwise. The equivalent configuration of the field list above, using a function for comparator, would be this:

const fields: Field[] = {
{ name: 'f1',
label: 'f1',
valueSources: ["field"],
comparator: f => f.datatype === 'number'
},
{ name: 'f2', label: 'f2', datatype: 'number' },
{ name: 'f3', label: 'f3', datatype: 'number' },
{ name: 'f4', label: 'f4', datatype: 'string' },
{ name: 'f5', label: 'f5', datatype: 'string' },
}