QuickForms provides pre-built components for all standard JSON Schema types.
Main form component that generates fields from JSON Schema.
interface DynamicFormProps {
schema: JSONSchema // JSON Schema definition
modelValue: any // Form data (v-model)
options?: FormOptions // Form configuration
}interface DynamicFormEmits {
'update:modelValue': (value: any) => void // Form data changed
'validation': (result: ValidationResult) => void // Validation state changed
}
interface ValidationResult {
valid: boolean
errors: Record<string, string>
}<script setup lang="ts">
import { ref } from 'vue'
import { DynamicForm } from '@quickflo/quickforms-vue'
import type { JSONSchema } from '@quickflo/quickforms'
const schema: JSONSchema = {
type: 'object',
properties: {
name: { type: 'string', title: 'Name' },
email: { type: 'string', format: 'email', title: 'Email' }
},
required: ['name', 'email']
}
const formData = ref({})
const handleValidation = (result: ValidationResult) => {
console.log('Valid:', result.valid)
console.log('Errors:', result.errors)
}
</script>
<template>
<DynamicForm
:schema="schema"
v-model="formData"
:options="{ validationMode: 'ValidateAndShow' }"
@validation="handleValidation"
/>
</template>None. The DynamicForm component automatically renders fields based on the schema. For customization, use the component registry.
Internal component that selects and renders the appropriate field component based on schema.
interface FieldRendererProps {
schema: JSONSchema
path: string
}Used internally by DynamicForm and container fields (ObjectField, ArrayField, OneOfField). You typically won't use this directly unless building a custom layout component.
<template>
<FieldRenderer :schema="fieldSchema" :path="fieldPath" />
</template>Pre-built components for each field type. All field components share the same props interface:
interface FieldProps {
schema: JSONSchema // Field's JSON Schema
path: string // Field path in form data
disabled?: boolean // Disable field input
readonly?: boolean // Make field read-only
}Renders text inputs for string fields.
type: 'string'- Various formats:
email,url,password,textarea
{
type: 'string',
title: 'Full Name',
minLength: 2,
maxLength: 100
}Format variants:
// Email
{ type: 'string', format: 'email' }
// URL
{ type: 'string', format: 'url' }
// Password
{ type: 'string', format: 'password' }
// Textarea
{ type: 'string', format: 'textarea' }Renders number inputs.
type: 'number'type: 'integer'
{
type: 'number',
title: 'Age',
minimum: 0,
maximum: 120
}{
type: 'integer',
title: 'Quantity',
multipleOf: 5
}Renders checkboxes for boolean values.
type: 'boolean'
{
type: 'boolean',
title: 'Accept Terms',
default: false
}Renders select dropdowns for enum values.
- Fields with
enumproperty
{
type: 'string',
title: 'Country',
enum: ['US', 'CA', 'UK', 'DE'],
'x-enum-labels': {
US: 'United States',
CA: 'Canada',
UK: 'United Kingdom',
DE: 'Germany'
}
}Multiple selection:
{
type: 'array',
title: 'Tags',
items: {
type: 'string',
enum: ['javascript', 'typescript', 'vue', 'react']
},
uniqueItems: true
}Renders date/time pickers.
format: 'date'format: 'time'format: 'date-time'
// Date
{
type: 'string',
format: 'date',
title: 'Birth Date'
}
// Time
{
type: 'string',
format: 'time',
title: 'Appointment Time'
}
// DateTime
{
type: 'string',
format: 'date-time',
title: 'Event Start'
}Renders nested object fields.
type: 'object'
{
type: 'object',
title: 'Address',
properties: {
street: { type: 'string', title: 'Street' },
city: { type: 'string', title: 'City' },
zip: { type: 'string', title: 'ZIP Code' }
},
required: ['street', 'city']
}Rendering:
- Plain Vue: Simple wrapper with nested fields
- Quasar: Expandable card with
QExpansionItem
Renders a JSON editor for freeform object configuration.
type: 'object'withadditionalPropertiesbut no definedproperties- Any field with
x-render: 'jsoneditor'
Auto-detected (freeform object):
{
type: 'object',
title: 'Custom Configuration',
description: 'Freeform JSON object',
additionalProperties: {}
}Explicit via x-render:
{
type: 'object',
title: 'API Settings',
description: 'Configuration in JSON format',
'x-render': 'jsoneditor',
'x-rows': 10 // Control textarea height
}With custom props (Quasar):
{
type: 'object',
title: 'Metadata',
'x-render': 'jsoneditor',
'x-rows': 8,
'x-quasar-props': {
dense: false,
color: 'secondary'
},
'x-quickforms-quasar': {
prependIcon: 'settings',
iconColor: 'primary',
showFormatHint: false // Hide info icon
}
}Hide format hint (Vue):
{
type: 'object',
'x-render': 'jsoneditor',
'x-show-format-hint': false // Hide info icon
}- Tab indentation: Press Tab to insert 2 spaces
- Format shortcut: Press Ctrl+Space to auto-format JSON
- Real-time validation: Shows parse errors as you type
- Monospace font: Better readability for JSON
- Info icon: Hover tooltip showing format shortcut (can be hidden)
- No auto-formatting: Only formats on initial load or manual trigger
- Ctrl+Space: Format JSON with proper indentation
- Tab: Insert 2 spaces for indentation
- Enter: Insert new line (does not submit form)
Global defaults (Quasar):
const formOptions = {
componentDefaults: {
jsoneditor: {
dense: true,
color: 'primary',
rows: 12
}
},
quickformsDefaults: {
jsoneditor: {
prependIcon: 'code',
iconColor: 'grey-7',
showFormatHint: true // Default: true
}
}
}Renders dynamic array fields with add/remove buttons.
type: 'array'
// Simple array
{
type: 'array',
title: 'Tags',
items: { type: 'string' }
}
// Array of objects
{
type: 'array',
title: 'Contacts',
items: {
type: 'object',
properties: {
name: { type: 'string', title: 'Name' },
phone: { type: 'string', title: 'Phone' }
}
},
minItems: 1,
maxItems: 5
}Features:
- Add/remove buttons
- Respects
minItemsandmaxItems - Drag-to-reorder (if enabled)
Renders conditional schemas with a selector.
- Schemas with
oneOf
{
oneOf: [
{
type: 'object',
title: 'Individual',
properties: {
name: { type: 'string', title: 'Full Name' },
ssn: { type: 'string', title: 'SSN' }
}
},
{
type: 'object',
title: 'Business',
properties: {
company: { type: 'string', title: 'Company Name' },
ein: { type: 'string', title: 'EIN' }
}
}
]
}Rendering:
- Dropdown to select which schema to use
- Dynamically renders fields based on selection
Renders merged schemas (intersection).
- Schemas with
allOf
{
allOf: [
{
type: 'object',
properties: {
name: { type: 'string', title: 'Name' }
}
},
{
type: 'object',
properties: {
email: { type: 'string', format: 'email', title: 'Email' }
}
}
]
}Behavior:
- Merges all schemas in
allOfarray - Renders as a single flat object
HiddenField
Renders a hidden input (no visual output).
- Fields with
'x-hidden': true
{
type: 'string',
'x-hidden': true,
default: 'hidden-value'
}Use Cases:
- Hidden form fields
- Tracking fields
- Server-side data
You cannot modify built-in components directly, but you can:
Register a custom component with higher priority:
import { createDefaultRegistry, rankWith, isStringType } from '@quickflo/quickforms-vue'
import CustomStringField from './CustomStringField.vue'
const registry = createDefaultRegistry()
// Override default StringField (priority 2) with priority 20
registry.register('custom-string', CustomStringField, rankWith(20, isStringType))Configure global defaults for all components:
import { createQuasarRegistry } from '@quickflo/quickforms-quasar'
const options = {
registry: createQuasarRegistry(),
componentDefaults: {
global: {
outlined: true,
dense: true
},
input: {
clearable: true
}
}
}Use schema extensions:
{
type: 'string',
title: 'Email',
'x-component-props': {
placeholder: 'you@example.com',
autocomplete: 'email'
}
}All field components receive these props automatically:
| Prop | Type | Description |
|---|---|---|
schema |
JSONSchema |
Field's JSON Schema definition |
path |
string |
Field path (e.g., "email", "user.name") |
disabled |
boolean |
Form-level disabled state |
readonly |
boolean |
Form-level readonly state |
Field components use useFormField(path, schema) to access:
value- Reactive field valueerrorMessage- Validation errorlabel- Display labelhint- Hint textrequired- Required status
See Composables API for details.
- Custom Components - Register your own components
- Composables API - Build custom field components
- Testers & Registry - Component selection system