Skip to main content

CnFormBuilder

Visual form composer. Three columns: a field-type palette (click to append), a reorderable field list, and a per-field config panel. Emits the live fields[] array via v-model so consumers can save / preview / render via CnFormDialog.

MVP. Drag-drop reorder is a follow-up — for now the field list uses up/down buttons. The v-model contract is forward-compatible so adding drag-drop later won't touch consumers.

Try it

<template>
<div>
<CnFormBuilder v-model="fields" @save="onSave" />
<hr>
<CnFormDialog
v-if="preview"
:schema="{ properties: schemaProperties(fields) }"
:item="null"
@close="preview = false" />
</div>
</template>

<script>
import { CnFormBuilder, CnFormDialog } from '@conduction/nextcloud-vue'

export default {
components: { CnFormBuilder, CnFormDialog },
data() { return { fields: [], preview: false } },
methods: {
schemaProperties(fields) {
// Translate to the CnFormDialog `properties` shape.
const out = {}
for (const f of fields) {
out[f.key] = { title: f.label, type: f.type === 'number' ? 'number' : 'string', ...(f.options ? { enum: f.options } : {}) }
}
return out
},
async onSave(fields) {
await axios.post('/api/forms', { fields })
},
},
}
</script>

Field shape

{
key: string,
type: 'string' | 'number' | 'boolean' | 'enum' | 'textarea',
label?: string,
placeholder?: string,
required?: boolean,
options?: string[], // only for type='enum'
}

Props

PropTypeDefaultDescription
valueArray<Field>[]v-model. Current field list.
availableTypesArray<{type,label,icon?}>default 5Extend / replace the palette.
title / descriptionString''Optional header.
hidePreviewBooleanfalseHide the JSON preview footer.
paletteTitle / fieldsTitle / editorTitle / previewTitleStringColumn headers.
emptyLabel / noSelectionLabel / untitledKeyStringState texts.
keyLabel / typeLabel / labelLabel / placeholderLabel / requiredLabel / optionsLabel / optionsPlaceholderStringPer-field editor labels.
moveUpLabel / moveDownLabel / deleteLabelStringRow-action button titles.

Events

EventPayloadDescription
inputArray<Field>v-model emit on every mutation.
saveArray<Field>Triggered by the public save() method. The parent renders the actual save UI.

Public methods

MethodDescription
save()Emit a @save with a copy of the current model.

Follow-up

  • Drag-drop reorder (HTML5 dragstart/dragover/drop on field rows).
  • Per-field validation rule editor (regex, min/max).
  • Live preview via embedded CnFormDialog.
  • Conditional visibility rules (showIf).