SurveyJS Compatibility

Copy Markdown View Source

DynamicForm can create a form from data. One way to define form data is with JSON.

DynamicForm's data format is compatible with SurveyJS form definitions: JSON produced for SurveyJS — by hand, by a WYSIWYG builder, or exported from SurveyJS Creator — decodes the JSON and renders with DynamicForm's own LiveView components. The compatibility is with the definition format, not the SurveyJS JavaScript runtime: rendering, validation, and submission are all server-side using Phoenix LiveView components and Ecto.

Pass SurveyJS JSON directly into the form component:

{
  "title": "Contact Form",
  "elements": [
    {"type": "text", "name": "name", "inputType": "text"},
    {"type": "text", "name": "email", "inputType": "email"}
  ]
}
<DynamicForm.form id="contact-form" json={@json} />

Supported

DynamicForm does not attempt to implement the entire SurveyJS functionality. Instead, it targets the most important and useful parts for building dynamic forms.

Question types

SurveyJS typeRenders asNotes
text<input>inputType passes through (email, number, ...); number casts to decimal
comment<textarea>
dropdown<select>
radiogroupRadio buttons
checkboxCheckbox groupArray-valued
tagboxMulti-selectArray-valued
booleanSingle checkbox
ratingNumeric radio rowrateMin/rateMax/rateStep (defaults 1–5)
fileDirect-to-cloud uploadConfigured via metadata (a DynamicForm extension) — see Usage: File uploads
paneldynamicRepeating child form with add/removeValue is a list of maps; each entry validates against templateElements with its own changeset — see the Nested Forms guide

Element types

SurveyJS typeRenders asNotes
htmlRaw HTML block
panelTitled containerNesting supported
image<img>imageLink, imageWidth, imageHeight, imageFit

Question properties

name, type, inputType, title, description, placeholder, defaultValue, choices, validators, isRequired, requiredIf, readOnly, enableIf, visibleIf, and rateMin/rateMax/rateStep.

For paneldynamic: templateElements (alias questions), templateTitle (with {panelIndex}), panelCount, minPanelCount, maxPanelCount, allowAddPanel, allowRemovePanel, addPanelText (alias panelAddText), removePanelText (alias panelRemoveText), noEntriesText, confirmDelete, confirmDeleteText, keyName, keyDuplicationError, and defaultPanelValue. Template expressions support the {panel.field} scope prefix. Not supported: displayMode/renderMode variants other than the default list (carousel, tab), templateVisibleIf, {parentPanel.*}/{prevPanel.*} references, and file uploads inside templates.

choices accepts plain strings (["a", "b"]), value/text objects ([{"value": "v", "text": "Label"}]), and integers.

Validators

SurveyJS validatorFields
textminLength, maxLength
numericminValue, maxValue
email
regexregex

Each accepts a custom error message via text. All validation runs server-side through an Ecto changeset.

Conditional expressions

visibleIf, requiredIf, and enableIf support: =, ==, <>, !=, >, <, >=, <=, empty, notempty, contains, notcontains, anyof, allof, noneof, combined with and, or, and parentheses. Field references use braces ({field}); literals are 'strings', numbers, booleans, and ['lists']. Hidden required questions are excluded from validation automatically.

Form-level

title and description decode onto the instance. Multi-page definitions (pages) are supported by flattening: all pages merge into a single form, with page titles preserved as headings.

Not Supported

Not exhaustive — the major and common SurveyJS features DynamicForm does not implement. Unknown question and element types don't fail the form: they are skipped (nothing renders — obvious in testing, not broken-looking in production) and the rest of the form works normally. Applications can also register their own types — see Usage: Custom field types.

FeatureNotes
Matrix types (matrix, matrixdropdown, matrixdynamic)matrixdynamic is a natural follow-up — it shares paneldynamic's data shape and validation machinery, rendered as a table
multipletextMultiple inputs in one question
signaturepad, imagepicker, ranking, sliderSpecialized input widgets
expression questions, calculated values, triggersNo expression evaluation beyond the conditional operators above (setValueIf, runexpression, quiz scoring, ...)
expression and answercount validatorsUse on_change for cross-field validation
Multi-page navigationPages are flattened into one form — no page-by-page navigation, progress bar, or per-page validation
Choice loading (choicesByUrl, lazy loading)Provide choices in the definition
showOtherItem / showNoneItem / showSelectAllItemChoice extras
Input masks
Localization objectsMulti-locale strings ({"default": ..., "de": ...}) aren't decoded; error messages translate via Gettext instead
SurveyJS themes and CSS customizationStyling is Tailwind via DynamicForm's components

DynamicForm extensions

Beyond the SurveyJS format, definitions can carry:

  • metadata — per-question extension point: file upload configuration, "style" ("horizontal"/"vertical") for radiogroup/checkbox layout.
  • generateIds — on by default for paneldynamic: every entry carries a stable dynamic_form_id, copied from the entry's id when the data came from a stored record. See Nested forms: Entry ids.
  • Declarative mode — the same instances can be defined with <:field> slots in HEEx, including custom markup via slot bodies (in-memory only; dropped on JSON encoding). See Usage: Defining forms.