Text Mode
Text mode lets the builder switch between the visual query UI and a SQL editor view of the same query.
Enable built-in text mode
import '@vojtechportes/react-query-builder/styles.css';import React, { useState } from 'react';import {Builder,type DenormalizedQuery,type IBuilderFieldProps,} from '@vojtechportes/react-query-builder';const fields: IBuilderFieldProps[] = [{field: 'CUSTOMER_COUNTRY',label: 'Customer country',type: 'LIST',operators: ['EQUAL', 'NOT_EQUAL'],value: [{ value: 'CZ', label: 'Czech Republic' },{ value: 'SK', label: 'Slovakia' },],},{field: 'ORDER_TOTAL',label: 'Order total',type: 'NUMBER',operators: ['LARGER_EQUAL', 'BETWEEN'],},];export const TextModeBuilder = () => {const [data, setData] = useState<DenormalizedQuery>(initialData);return (<Builderfields={fields}data={data}textModeonChange={setData}/>);};
Current scope
- Text mode currently uses SQL as the editable text format.
- It requires
singleRootGroupto stay enabled. IfsingleRootGroupisfalse, text mode is unavailable and the builder stays in visual mode. - When text mode is enabled, modifierless groups are normalized to
ANDgroups so the query can round-trip through SQL.
Opening mode
Use defaultMode to choose whether the builder opens in the visual builder or in text mode.
Open directly in text mode
import '@vojtechportes/react-query-builder/styles.css';<Builderfields={fields}data={data}textModedefaultMode="text"onChange={setData}/>;// defaultMode only takes effect when textMode is enabled.
Explicit textMode config
import '@vojtechportes/react-query-builder/styles.css';<Builderfields={fields}data={data}textMode={{format: 'SQL',defaultMode: 'builder',}}defaultMode="text"onChange={setData}/>;// textMode can be either:// - true// - { format?: 'SQL'; defaultMode?: 'builder' | 'text' }//// If both are provided, the top-level defaultMode prop wins.
Validation
- Missing brackets, quotes, commas, and other SQL syntax mistakes are highlighted directly in the editor.
- Unknown fields are highlighted on the field token.
- Unsupported operators for a field are highlighted on the operator token.
- Invalid
LISTvalues are highlighted on the invalid value token. - Invalid
MULTI_LISTvalues are highlighted on the invalid value token. - Read-only negation changes are rejected after parsing and shown as below-editor semantic errors.
Invalid text behavior
- Invalid text stays local to the text editor until the SQL becomes valid again.
- The last valid builder query is preserved while the user is fixing text-mode errors.
onChangeis fired only after a valid parse and successful semantic validation.
History behavior
- Valid text edits are committed into builder history, so they can be undone and redone.
- Invalid intermediate text is not committed into builder state or history.
Choosing an editor
- Choose the built-in editor when you want lightweight SQL editing, built-in validation, and no extra dependencies.
- Choose Monaco when locked or targeted read-only query segments must stay protected in text mode, or when you want a more advanced editor experience.
Built-in editor vs Monaco
- Built-in text mode Included in the core package, uses the default
TextModeEditor, and supports SQL formatting, syntax highlighting, syntax validation, and semantic validation without extra dependencies. - Built-in editor limitation Locked rules, locked groups, and targeted read-only queries are blocked before entering text mode there, because the basic editor cannot preserve protected query segments safely after freeform text edits.
- Monaco text mode Optional advanced editor integration exposed from
@vojtechportes/react-query-builder/monaco. It preserves locked and targeted read-only query segments by rendering them as protected ranges. - Monaco protected behavior Protected SQL fragments are dimmed, protected from edits, and expose their lock explanation on hover. The packaged Monaco light and dark themes use the same query-builder palette roles as the built-in editor for SQL tokens. An explicit Builder
colorSchemeswitches between them without remounting the editor. Because Monaco's standalone theme service is global, the latest mounted packaged editor, or the editor whose scheme changes most recently, wins across all mounted Monaco editors. - Localized read-only protection Rule field, operator, and value segments can be protected inline, while read-only negation is additionally enforced semantically and reported below the editor when changed.
- Group negation validation When
allowGroupNegation=, the text editor rejects group-levelNOT (...)expressions and highlights the offendingNOTtoken, while still allowing operator-level negation such asNOT INorIS NOT NULL. - Monaco packaging
monaco-editoris an optional peer dependency. Consumers only need to install it when they actually want the Monaco editor.
Using Monaco text mode
Monaco uses the same public @vojtechportes/react-query-builder/styles.css import as the default builder. Import it once; the Monaco subpackage does not ship a second stylesheet.
Monaco text mode with default components
import '@vojtechportes/react-query-builder/styles.css';import React, { useState } from 'react';import {Builder,type DenormalizedQuery,} from '@vojtechportes/react-query-builder';import { createMonacoComponents } from '@vojtechportes/react-query-builder/monaco';const components = createMonacoComponents({});export const MonacoTextModeBuilder = () => {const [data, setData] = useState<DenormalizedQuery>(initialData);return (<Builderfields={fields}data={data}textModedefaultMode="text"components={components}onChange={setData}/>);};
Compose Monaco with MUI
import '@vojtechportes/react-query-builder/styles.css';import { Builder } from '@vojtechportes/react-query-builder';import { components as muiComponents } from '@vojtechportes/react-query-builder/mui/v9';import { createMonacoComponents } from '@vojtechportes/react-query-builder/monaco';const components = createMonacoComponents(muiComponents);<Builderfields={fields}data={data}textModecomponents={components}onChange={setData}/>;// The same pattern works with @vojtechportes/react-query-builder/antd/v6.
Compose Monaco with ANTD
import '@vojtechportes/react-query-builder/styles.css';import { Builder } from '@vojtechportes/react-query-builder';import { components as antdComponents } from '@vojtechportes/react-query-builder/antd/v6';import { createMonacoComponents } from '@vojtechportes/react-query-builder/monaco';const components = createMonacoComponents(antdComponents);<Builderfields={fields}data={data}textModecomponents={components}onChange={setData}/>;
Monaco styling hooks
- Use public editor, color, spacing, radius, and shadow CSS variables for supported presentation changes.
.rqb-monaco-text-mode-editoris the stable class on the Monaco surface when an application needs a wrapper-scoped selector.- Generated
rqb_[local]_[hash]CSS Module classes are private and must not be used as selectors.
Text-mode strings
Text-mode labels and messages are part of the regular strings override surface.
Custom text-mode strings
import '@vojtechportes/react-query-builder/styles.css';import { strings } from '@vojtechportes/react-query-builder';<Builderfields={fields}data={data}textModestrings={{...strings,textMode: {...strings.textMode,toggleToText: 'Switch to SQL mode',toggleToBuilder: 'Switch to visual builder',syntaxError: 'SQL syntax error',locksUnsupported: 'Locked rules and groups are not supported in this text editor mode.',lockedRangesHover: 'This SQL fragment is locked and cannot be edited.',},}}onChange={setData}/>;
strings.textMode.toggleToTextcustomizes the button label for entering text mode.strings.textMode.toggleToBuildercustomizes the button label for returning to the visual builder.strings.textMode.syntaxErrorcustomizes the syntax error prefix.strings.textMode.locksUnsupportedcustomizes the built-in alert shown when the basic editor cannot open a locked or targeted read-only query.strings.textMode.lockedRangesHovercustomizes the hover message shown for protected Monaco ranges.strings.textMode.sqlcustomizes SQL parser and syntax-validation messages such as missing brackets, missing quotes, missing keywords, and unexpected tokens.
Installing Monaco
Monaco peer dependency
npm install monaco-editor
Locks and Monaco
The built-in text editor blocks locked and targeted read-only queries. Monaco is the intended path when protected query segments need to remain editable only around their unlocked ranges.
API reference
Builder and Components.