Component

JSON input

<DomJsonInput>

A JSON form input backed by DomCodeInput. Valid JSON emits parsed data; invalid JSON stays local and shows an error.

Playground

Try every prop live

JSON input playground

The JSON input is useful anywhere a form needs to expose structured data without hiding the raw value.

Editable

Valid JSON emits parsed data.

Playground.vuevue
<script setup>
import { reactive } from 'vue';
import { DomJsonInput } from '@getdom/studio/vue';

const data = reactive({
	  "modelValue": {
	    "name": "DOM Studio",
	    "editable": true
	  },
	  "id": "",
	  "name": "",
	  "label": "Feature config",
	  "description": "Valid JSON emits parsed data.",
	  "placeholder": "",
	  "required": false,
	  "disabled": false,
	  "readOnly": false,
	  "invalid": false,
	  "errors": {},
	  "visible": true,
	  "validators": [],
	  "validateOnBlur": true,
	  "chrome": "field",
	  "rows": 8,
	  "editor": true,
	  "schema": null,
	  "jsonToggle": true,
	  "compact": false
	});
</script>

<template>
	<DomJsonInput
		v-bind="data"
		@update:modelValue="data.modelValue = $event"
	/>
</template>

Demo

JSON form input

Invalid JSON shows an inline error and does not emit until the value is valid again.

Flags

Studio
Ai

Valid JSON emits parsed data. Invalid JSON is held locally until fixed.

{
  "name": "DOM Studio",
  "plan": "Pro",
  "flags": {
    "studio": true,
    "ai": true
  }
}
JsonField.vuevue
<script setup>
import { ref } from 'vue';
import { DomJsonInput } from '../../../lib/vue';

const value = ref({
	name: 'DOM Studio',
	plan: 'Pro',
	flags: {
		studio: true,
		ai: true,
	},
});
</script>

<template>
	<div class="w-full max-w-2xl space-y-4">
		<DomJsonInput
			v-model="value"
			label="Feature config"
			description="Valid JSON emits parsed data. Invalid JSON is held locally until fixed."
			:rows="10"
		/>
		<pre class="overflow-auto rounded-xl border border-border bg-secondary/50 p-3 text-xs text-muted-fg">{{ value }}</pre>
	</div>
</template>

Demo

Form plus raw JSON

A standardized form schema renders common edits as fields, while the JSON tab stays available for manual changes.

Active team

Billing contact

Row 1
Row 2

The same schema renders field controls and a raw JSON editor.

{
  "teamName": "Platform team",
  "ownerEmail": "platform@example.com",
  "defaultRole": "member",
  "active": true,
  "billing": {
    "name": "Alex Morgan",
    "email": "billing@example.com"
  },
  "invites": [
    {
      "email": "maya@example.com",
      "role": "admin"
    },
    {
      "email": "noah@example.com",
      "role": "viewer"
    }
  ]
}
FormAndJson.vuevue
<script setup>
import { ref } from 'vue';
import { DomJsonInput } from '../../../lib/vue';

const config = ref({
	teamName: 'Platform team',
	ownerEmail: 'platform@example.com',
	defaultRole: 'member',
	active: true,
	billing: {
		name: 'Alex Morgan',
		email: 'billing@example.com',
	},
	invites: [
		{ email: 'maya@example.com', role: 'admin' },
		{ email: 'noah@example.com', role: 'viewer' },
	],
});

const schema = {
	type: 'DomForm',
	properties: {
		teamName: {
			type: 'string',
			label: 'Team name',
			required: true,
			placeholder: 'Platform team',
		},
		ownerEmail: {
			type: 'email',
			label: 'Owner email',
			required: true,
		},
		defaultRole: {
			type: 'string',
			component: 'DomSelectInput',
			label: 'Default role',
			options: [
				{ label: 'Admin', value: 'admin' },
				{ label: 'Member', value: 'member' },
				{ label: 'Viewer', value: 'viewer' },
			],
		},
		active: {
			type: 'boolean',
			label: 'Active team',
		},
		billing: {
			type: 'DomForm',
			label: 'Billing contact',
			properties: {
				name: {
					type: 'string',
					label: 'Contact name',
				},
				email: {
					type: 'email',
					label: 'Contact email',
				},
			},
		},
		invites: {
			type: 'array',
			label: 'Invites',
			items: {
				type: 'DomForm',
				properties: {
					email: {
						type: 'email',
						label: 'Invitee email',
						required: true,
					},
					role: {
						type: 'string',
						component: 'DomSelectInput',
						label: 'Role',
						options: [
							'admin',
							'member',
							'viewer',
						],
					},
				},
			},
		},
	},
};
</script>

<template>
	<div class="grid w-full max-w-4xl gap-5 lg:grid-cols-[minmax(0,1fr)_20rem]">
		<DomJsonInput
			v-model="config"
			label="Team setup"
			description="The same schema renders field controls and a raw JSON editor."
			:schema="schema"
			:rows="15"
		/>
		<pre class="max-h-[34rem] overflow-auto rounded-xl border border-border bg-secondary/50 p-3 text-xs text-muted-fg">{{ config }}</pre>
	</div>
</template>

Reference

Props

Control props

NameTypeTSDefaultDescription
modelValueanyanyAny JSON-serializable value.
rowsnumbernumber10Textarea fallback rows.
editorbooleanbooleantrueAttempt to load the enhanced editor from the CDN.
schemaobject | arrayArray<unknown>Optional standardized form definition used to render a visual JSON editor.
jsonTogglebooleanbooleantrueShow the visual/raw JSON mode switch when schema is provided.
compactbooleanbooleanfalseReduce vertical spacing for schema-driven editors.

Field props

NameTypeTSDefaultDescription
idstringstring''Optional ID override. By default parent forms derive the input ID from the field path using underscores.
namestringstring''Local field name. Parent forms derive the full field path and native HTML name from the form hierarchy.
labelstringstring''Visible field label.
descriptionstringstring''Optional helper copy below the field.
placeholderstringstring''Placeholder shown when the control is empty.
requiredbooleanbooleanfalseMark the field as required.
disabledbooleanbooleanfalseDisable field interaction.
readOnlybooleanbooleanfalseShow the value but prevent editing.
invalidbooleanbooleanfalseMark the field invalid.
errors
[
	{
		name: "Validation name",
		message: "Error message",
	}
]
array | object | stringArray<ErrorsItem
type ErrorsItem = {
	name?: string; // Name
	message?: string; // Message
};
>
{}Validation errors for this field.
visiblebooleanbooleantrueShow or hide the field.
validatorsarrayArray<unknown>[]Validators attached to this field. Use functions in Vue code, or serializable records such as { name: "minLength", props: { min: 2 } } in generated schemas.
validateOnBlurbooleanbooleantrueRun validators when the field loses focus.
chrome'field' | falsestring'field'Render default field chrome, or false to render only the control while keeping form state wiring.

Auto-generated from JSON input.props and inline _edit hints.

Events

NamePayloadDescription
@update:modelValueobject | array | string | number | boolean | nullFired with parsed JSON when the editor contains valid JSON.
@validparsed valueFired when JSON parses successfully.
@invalidErrorFired when JSON cannot be parsed.
@focus
@blur

Names auto-detected from defineEmits and source emit() calls; payload and description from __doc.events when present.