Skip to content

Community catalog: fields, static content and structures

QForm Builder Community provides an extensible catalog built exclusively with Quasar 2, FormKit and Vue 3. It follows the familiar organization of professional form builders: input fields, static content and structures.

Included fields

  • text, textarea, number, email, phone, password, URL and color;
  • rich text editor;
  • checkbox, toggle, checkbox group and radio group;
  • single select, multiselect and button toggle;
  • date, multiple dates, date range, time and date/time;
  • slider, numeric range and rating;
  • file, multiple files and hidden field.

Every field is rendered by a FormKit adapter backed by a Quasar 2 component. The schema remains JSON serializable.

Hidden-field data

The q-hidden field now has a dedicated Data settings section. It controls:

The layer pre-bundles @formkit/inputs, which provides numeric casting, so the first Data-panel render does not trigger a Vite reload on Windows.

  • a literal text or numeric value;
  • a FormKit expression starting with $;
  • numeric coercion through the FormKit number prop;
  • inclusion in, or exclusion from, submitted data through ignore.

Literal values use the schema key __raw__value, preventing strings that start with $ from being interpreted as expressions. The __raw__ prefix is a FormKit schema mechanism and is not forwarded as part of the rendered prop name. Expressions are length-bounded, validated and reject dangerous global or prototype tokens. The panel does not accept arbitrary JavaScript.

Example:

ts
{
  $formkit: 'q-hidden',
  name: 'version',
  __raw__value: 1,
  number: 'float',
}

To temporarily exclude the field from the submitted model:

ts
{
  $formkit: 'q-hidden',
  name: 'version',
  __raw__value: 1,
  ignore: true,
}

Dedicated checks:

powershell
bun run hidden-data:check
bun run e2e:hidden-data

File fields use the dedicated q-file / QFile FormKit type. They provide consistent Quasar rendering, native drag and drop, accept, maxFileSize, maxTotalSize and maxFiles restrictions, chips and a counter. Historical schemas based on q-input with inputType: 'file' remain supported by the compatibility adapter. Runtime values are File or File[] objects: transferring them to Feathers/NFZ or object storage is the host application's responsibility and must not be confused with the form JSON schema.

Quasar 2 adapter contract

Catalog adapters now follow the actual Quasar 2 component contract and no longer forward ineffective properties:

  • QCheckbox, QToggle, QOptionGroup, QBtnToggle, QSlider, QRange, QRating and QEditor render labels, help text and errors through one accessible, dark-mode-aware feedback layer;
  • checkboxes and toggles preserve custom true-value / false-value models instead of coercing every value to Boolean;
  • readonly is mapped to disable for Quasar controls that do not expose a read-only prop;
  • sliders normalize min, max and step, including imported schemas;
  • the rich text editor keeps a genuinely empty value, so its placeholder is never persisted as content;
  • date/time fields honor disable and readonly, display their label and block popup or clear actions while locked;
  • buttons use only the native button, submit or reset types and never store a click event in the form model;
  • dynamic attributes starting with on, and active keys such as innerHTML, are filtered before reaching Quasar components.

Tabs expose overflow arrows on small screens and preserve panel state. Columns, sections, fieldsets, hidden-field previews and helper text also share consistent light/dark rendering.

Dedicated checks:

powershell
bun run quasar-adapters:check
bun run quasar-adapters:runtime:check

Static elements

  • required privacy consent (privacy_consent);
  • submit, primary, secondary and danger buttons;
  • separator and spacer;
  • H1 to H6 headings, paragraph and quote;
  • link and image;
  • information and warning banners;
  • code block.

Links, images and spacers expose dedicated settings in the properties panel.

Structures

  • QCard section;
  • semantic fieldset group;
  • responsive Quasar columns;
  • Quasar tabs;
  • multi-step form with QStepper.

Structures are real editable containers. Sections, fieldsets, columns and tabs expose nested drop zones. A field can be added from the catalog, moved from one column to another, moved back to the root or transferred into another structure while keeping a JSON-serializable schema.

Drag and drop inside containers

The q-columns type represents a container made of Quasar columns. Each column owns its own fields collection:

ts
{
  $formkit: 'q-columns',
  name: 'contactColumns',
  columnsDefinition: [
    { name: 'identity', label: 'Identity', width: 6, fields: [] },
    { name: 'contact', label: 'Contact', width: 6, fields: [] },
  ],
}

In the builder:

  1. drop the Two columns structure onto the canvas;
  2. drop a field directly into an empty column zone;
  3. move the field between the root, columns, sections, fieldsets and tabs;
  4. use the container name tag to select, move or remove the structure itself.

The store recursively locates every field by name and prevents cyclic moves, such as moving a container into one of its own descendants. Added and duplicated field names are recursively normalized to remain unique.

Dedicated check:

powershell
bun run nested:check

Select and configure a column

Each column is now an editable node independent from its q-columns container. Click its header in the canvas, or select it from the tree, to open the column settings panel.

Available options:

  • technical name unique inside the container;
  • label, tooltip and description;
  • values nested under the column name;
  • text decorators before, between and after fields;
  • separate responsive widths for default, tablet and desktop views;
  • width inheritance between breakpoints;
  • duplicate and remove actions.

The JSON model remains backward compatible with the legacy width property and now uses widths for breakpoints:

ts
{
  name: 'identity',
  label: 'Identity',
  info: 'Personal information',
  description: 'Fields related to identity.',
  nestedData: true,
  before: 'Column start',
  between: 'Separator',
  after: 'Column end',
  width: 6,
  widths: {
    default: 12,
    sm: 6,
    lg: 4,
  },
  fields: [],
}

When nestedData is true, the values of the fields inside the column are grouped under the column name in the FormKit model.

Dedicated check:

powershell
bun run column:check

FormKit runtime registration

The 24 q-* catalog types are registered by the layer formkit.config.ts. The published nuxt.config.ts uses an absolute path resolved from import.meta.url, preventing an implicit playground configuration file from shadowing new adapters.

Check:

powershell
bun run formkit:check

Customize the catalog

The catalog prop appends or replaces elements:

vue
<script setup lang="ts">
import { defineQFormElement } from '@vevedh/qform-builder-layer/catalog'

const customCatalog = [
  defineQFormElement({
    key: 'employeeId',
    category: 'fields',
    icon: 'badge',
    title: 'Employee ID',
    description: 'Internal identifier',
    schema: {
      $formkit: 'q-input',
      name: 'employeeId',
      label: 'Employee ID',
      inputType: 'text',
    },
  }),
]
</script>

<template>
  <FormBuilder
    builder-id="employees"
    :catalog="customCatalog"
    catalog-mode="append"
  />
</template>

Available modes:

  • append: keeps the Community catalog and overrides matching keys;
  • replace: uses only the catalog supplied by the host application.

Test in the playground

powershell
bun run clean && bun i && bun run typecheck && bun dev

Then open:

text
http://localhost:3000/catalog

Column layout designer

When the q-columns container is selected, the Column layout panel manages the structure without manually editing JSON.

Available presets for the active viewport:

  • one 12/12 column;
  • two equal 6/12 + 6/12 columns;
  • narrow left column 4/12 + 8/12;
  • narrow right column 8/12 + 4/12;
  • three equal 4/12 columns;
  • four equal 3/12 columns.

The column count is adjusted automatically. When a preset reduces the number of columns, fields from removed columns are moved into the last remaining column, so schema data is never discarded.

The panel can also:

  • add a column;
  • move a column left or right;
  • duplicate a column and its fields;
  • remove a column except the last one;
  • open detailed settings for a column;
  • apply separate widths for mobile, tablet and desktop.

Dedicated check:

powershell
bun run columns-layout:check

The viewport buttons below Edit/Preview control the same responsive context used by the column designer.

QBtn buttons: label, tooltip and description

Since version 0.1.3, a button panel no longer exposes two competing text properties. The visible button text is controlled only by buttonLabel through Button label.

The Tooltip property is stored in info and rendered with a real Quasar child component:

vue
<q-btn :label="buttonLabel">
  <q-tooltip v-if="buttonTooltip">
    {{ buttonTooltip }}
  </q-tooltip>
</q-btn>

Vue interpolation escapes the value; it is never injected as HTML. description remains separate explanatory text below the button. Legacy schemas may still use label as a runtime fallback when buttonLabel is missing.

Shared tooltips for all elements

Since version 0.1.5, the Tooltip property is enabled by default in shared property panels. Its serializable value is stored in info.

In the builder preview, nested containers, steps and FormViewer, hovering the complete element triggers a native Quasar component:

vue
<div class="form-field">
  <FormKitSchema :schema="field" />
  <q-tooltip v-if="field.info">
    {{ field.info }}
  </q-tooltip>
</div>

QTooltip is a direct child of its DOM or Quasar target. Regular fields use the .form-field renderer container. Elements that contain nested fields — q-section, q-fieldset, q-columns, q-tabs-structure, and q-stepper — own a dedicated header or legend target so a parent tooltip does not compete with child tooltips. q-btn also keeps its specialized target: QTooltip remains a direct child of QBtn. Static content and columns no longer rely on a separate small information icon; their relevant surface becomes the hover target.

The /qtooltip-audit playground route and its Playwright scenario cover generic fields, QBtn, QBtnToggle, static content, and every structure family. The tooltip:check gate also scans every SFC to forbid v-show on QTooltip and detect tooltips placed below a <template> instead of a concrete target.

Content is trimmed, bounded and escaped by Vue interpolation. Never use v-html for schema-provided tooltip content.

Advanced QEditor, QSelect and QRating options

Version 0.1.2 adds dedicated panels for the three components with the richest Quasar contracts.

QEditor

  • minimal, standard and full toolbar presets;
  • div or p paragraph tag;
  • controlled minimum, maximum or fixed CSS heights;
  • dense, flat, square and toolbar button styles;
  • background, text, active-state and general colors.

QSelect

  • single or multiple selection with automatic model normalization;
  • chips, local search, debounce and maximum selections;
  • emit-value, map-options, option-label, option-value and option-disable;
  • automatic, menu or dialog behavior;
  • controlled creation of new values;
  • option HTML rendering deliberately disabled so a serializable schema cannot inject active content.

QRating

  • icon count from 1 to 100;
  • size, empty, selected and half icons;
  • separate colors;
  • ARIA label;
  • no-reset and no-dimming options.

Normalization helpers are public:

ts
import {
  filterQFormBuilderSelectOptions,
  normalizeQFormBuilderCssSize,
  normalizeQFormBuilderSelectModel,
  resolveQFormBuilderEditorToolbar,
} from '@vevedh/qform-builder-layer/quasar-options'

Dedicated checks:

bash
bun run quasar-advanced:check
bun run quasar-advanced:runtime:check

Single drop indicator

At the boundary between two fields, the same logical destination could previously be represented by the first field's “after” zone and the second field's “before” zone. Both Drop here labels could therefore be visible at the same time.

This was not expected behavior. The active indicator is now identified by its target container, reference field and exact before or after position. Only one line is rendered for one drop destination.

Dedicated check:

bash
bun run drop-indicator:check

Playwright visual scenarios

The following playground route covers runtime rendering, advanced panels and the drop indicator:

text
http://localhost:3000/quasar-advanced

Commands:

bash
bun run e2e:visual:update  # create or approve new references
bun run e2e:visual         # detect a visual regression
bun run e2e:report         # open the HTML report

Reference screenshots should only be regenerated after an intentional visual review. To create a business component and its matching panel, read the custom components and panels guide.

QForm Builder — Nuxt 4, Quasar and FormKit layer for dynamic forms.