JsonInput
The built-in jsoninput tag — a textarea that validates JSON and can pretty-print it on blur, with autosize and a custom validation message.
A JSON-aware textarea: it validates the content as JSON and can reformat it on blur. It
carries the same Input wrapper as TextInput and the
multi-line behaviour of Textarea, plus the JSON
specifics: formatOnBlur (pretty-print on blur) and validationError (the message shown for
invalid JSON). Reach for it for config blobs, payload editors, and metadata fields.
Use it as {% jsoninput %} in Markdown, or call it from Python logic
(loops, snippets) via component('aardvark', 'jsoninput', …).
Basic field
A label and a placeholder. With formatOnBlur on, valid JSON is pretty-printed when the
field loses focus; autosize plus minRows sizes the box.
Type some JSON and click away — valid JSON is reformatted; invalid JSON shows the validation message.
{% jsoninput label='Config' placeholder='{ "key": "value" }' formatOnBlur=true autosize=true minRows=4 %}
component('aardvark', 'jsoninput', label='Config',
placeholder='{ "key": "value" }', formatOnBlur=True,
autosize=True, minRows=4)
Custom validation message
validationError is the message shown when the content isn’t valid JSON.
That is not valid JSON
{% jsoninput label='Payload' validationError='That is not valid JSON' formatOnBlur=true autosize=true minRows=3 defaultValue='{ broken: }' %}
component('aardvark', 'jsoninput', label='Payload',
validationError='That is not valid JSON', formatOnBlur=True,
autosize=True, minRows=3, defaultValue='{ broken: }')
Autosize bounds
autosize grows the field with its content; minRows is then the floor and maxRows the
cap, after which the field scrolls instead of growing. Both are read only while autosize
is on — on a fixed-height field they are ignored and the browser’s default two-row textarea
is what you get.
{% jsoninput label='Metadata' autosize=true minRows=2 maxRows=10 placeholder='{ }' formatOnBlur=true %}
component('aardvark', 'jsoninput', label='Metadata', autosize=True,
minRows=2, maxRows=10, placeholder='{ }', formatOnBlur=True)
Required, error, and disabled
required and withAsterisk add the asterisk; error shows a wrapper-level validation
message; disabled greys the control out.
At least one rule is required
{% jsoninput label='Webhook body' required=true autosize=true minRows=3 placeholder='{ }' %}
{% jsoninput label='Rules' error='At least one rule is required' autosize=true minRows=3 defaultValue='[]' %}
{% jsoninput label='Frozen config' disabled=true autosize=true minRows=3 defaultValue='{ "env": "prod" }' %}
component('aardvark', 'jsoninput', label='Webhook body', required=True,
autosize=True, minRows=3, placeholder='{ }')
component('aardvark', 'jsoninput', label='Rules',
error='At least one rule is required', autosize=True, minRows=3,
defaultValue='[]')
component('aardvark', 'jsoninput', label='Frozen config', disabled=True,
autosize=True, minRows=3, defaultValue='{ "env": "prod" }')
Variants, size, and radius
variant is default, filled, or unstyled; size and radius take xs–xl.
{% jsoninput label='Filled' variant='filled' autosize=true minRows=3 placeholder='{ }' %}
{% jsoninput label='Large, round' size='lg' radius='lg' autosize=true minRows=3 placeholder='{ }' %}
component('aardvark', 'jsoninput', label='Filled', variant='filled',
autosize=True, minRows=3, placeholder='{ }')
component('aardvark', 'jsoninput', label='Large, round', size='lg',
radius='lg', autosize=True, minRows=3, placeholder='{ }')
With other components
Pair a name field with a JSON config editor inside a {% card %}.
{% card title='New integration' %}
{% textinput label='Name' placeholder='My integration' required=true %}
{% jsoninput label='Settings (JSON)' formatOnBlur=true autosize=true minRows=4 placeholder='{ "enabled": true }' %}
{% endCard %}
name = component('aardvark', 'textinput', label='Name',
placeholder='My integration', required=True)
settings = component('aardvark', 'jsoninput', label='Settings (JSON)',
formatOnBlur=True, autosize=True, minRows=4,
placeholder='{ "enabled": true }')
component('aardvark', 'card', title='New integration',
children=name + settings)
Validity is judged when the field loses focus and cleared again the moment it regains focus,
so the message appears once you click away rather than on every keystroke. An empty field
counts as valid — the check only complains about content it cannot parse, so pair the field
with required if a value is mandatory. If you leave validationError unset, invalid JSON
still turns the field red but carries no message, so it is worth setting. formatOnBlur
re-indents with two spaces, and only when the content parses and is not blank; broken JSON is
left exactly as typed so nothing you wrote is lost.
Attributes
Omit any attribute to take its Mantine default.
| Attribute | Valid values | Description |
|---|---|---|
label |
string | Field label above the input. |
description |
string | Helper text below the label. |
placeholder |
string | Placeholder shown when the field is empty. |
error |
string | Wrapper-level validation message; switches the field to the error color. |
defaultValue |
string | Initial value of the field. |
formatOnBlur |
bool (true / false) |
Pretty-print valid JSON when the field loses focus. |
validationError |
string | Message shown when the content isn’t valid JSON. |
autosize |
bool (true / false) |
Grow the field with its content. |
minRows |
integer | Shortest the field gets, in rows. Read only when autosize is on. |
maxRows |
integer | Tallest the field grows to before it scrolls. Read only when autosize is on. |
variant |
default, filled, unstyled |
Visual style of the input. |
size |
xs, sm, md, lg, xl |
Control size. |
radius |
xs, sm, md, lg, xl, or any CSS length |
Corner radius. |
required |
bool (true / false) |
Mark the field required and add the asterisk. |
withAsterisk |
bool (true / false) |
Add the asterisk without the HTML required attribute. |
disabled |
bool (true / false) |
Render the field disabled. |
CSS Selectors
Target a {% jsoninput %} from your own CSS with the island data attribute or the Mantine Styles API part classes:
/* Every JsonInput instance on the page */
[data-aardvark-island="JsonInput"] { }
/* Mantine Styles API parts */
.mantine-JsonInput-root { }
.mantine-JsonInput-input { }
.mantine-JsonInput-label { }
Injecting Attributes
Pass attr={…} to forward raw HTML attributes — including inline event handlers — straight onto the rendered element. Here it is wired to onchange, so changing the field logs its new value to the console and alerts it:
{% jsoninput label='Config' placeholder='{ "key": "value" }' formatOnBlur=true autosize=true minRows=4 attr={'onchange': '''
const value = this.value;
console.log('attr demo value:', value);
alert(value);
'''} %}
component('aardvark', 'jsoninput', label='Config',
placeholder='{ "key": "value" }', formatOnBlur=True,
autosize=True, minRows=4, attr={'onchange': '''
const value = this.value;
console.log('attr demo value:', value);
alert(value);
'''})