Prompt
How do I build complex forms in Vue.js?
Latest observation
Here's how to build complex forms in Vue.js, covering what "complex" actually means and the current recommended approaches for each aspect.
What makes a form "complex" — worth defining first A useful framing from current sources: complexity generally shows up as one or more of: multi-step flows (checkout-style, needing state preserved across steps), nested/repeating sections (separate billing and shipping addresses, multi-person booking forms), and validation across many interdependent fields. Each of these needs a different technique, not one silver bullet.
- Component composition — the foundational pattern Break the form into small, reusable components rather than one giant template:
Create dedicated components per field type (BaseInput.vue, FieldCardSelector.vue) using v-model for two-way binding (covered in more depth in an earlier Vue reusable-forms question in this conversation) Use v-for to render repeated structures (multiple steps, repeated field groups) from an array rather than hardcoding each instance Use scoped slots when a component needs to accept custom markup from its parent, rather than adding more and more boolean props to control appearance
- Config-driven fields — reduces boilerplate for many similar inputs Define your form's field metadata in a JSON file (e.g., bio-data.json) rather than manually writing out each input element in the template:
json { "name": "email", "label": "Email Address", "type": "email", "required": true }
Then loop over this config with v-for to generate inputs dynamically. The practical benefit: extending the form later just means adding to the JSON — no new engineer needs to read through long template code to understand what fields exist, and the same input component gets reused for every field of that type.
-
Multi-step forms — needs state management across views For anything checkout-style, where data must persist as the user navigates between steps, use Pinia (Vue's current standard state management library) to hold form state centrally rather than passing values through props/emits across many components. This is the recommended pattern specifically because multi-step forms often involve navigating away from and back to a step, and component-local state would reset on remount.
-
Validation — Zod plus a form library, not hand-rolled rules The current recommended combination is Zod for schema-based validation logic, paired with a Vue form library that wires validation into your components — this mirrors what's covered in more depth in earlier Vue validation questions in this conversation (VeeValidate + Zod specifically). Zod gives you a single source of truth for what "valid" means per field, rather than scattering ad hoc validation checks across components.
-
Nested and repeating sections For structures like separate billing/shipping addresses or multi-person booking forms, either:
Nest components (an AddressForm.vue used twice with different v-model bindings), or Use a library with built-in repeatable field-group support — Vue Formulate specifically ships this out of the box, letting you generate complex UIs like multi-person booking forms without hand-rolling the repeat/add/remove logic yourself
- If you want most of this handled for you: a dedicated complex-forms framework
Vueform — positions itself specifically as a comprehensive form development framework rather than a component library: 25+ form elements (including multi-file uploads, date pickers, rich text editor), element nesting and repeating, 50+ validators (async, dependent, custom rules), conditional logic at both element and form level, and native form-wizard support for breaking a form into steps. Forms save as JSON to your database, and it includes a drag-and-drop builder that lets non-technical team members build complex forms without writing code Vue Formulate — generates entire forms from a JSON schema with groups, wrappers, and custom components; a single component handles all form element types rather than needing to remember a dozen different component names
Practical recommendation, by complexity level
Moderate complexity (a handful of steps, standard validation) → component composition + Pinia for cross-step state + VeeValidate/Zod for validation, hand-built with your own components High complexity, many repeating/nested sections, want less boilerplate → Vue Formulate for its built-in repeatable groups and JSON-driven generation Very high complexity, want a full framework with conditional logic, multi-step wizards, and a visual builder for non-technical collaborators → Vueform
For a genuinely deep, book-length treatment of this exact topic, Marina Mosti's Building Forms with Vue.js (Packt) walks through component composition, Vuelidate/Vuex integration, input masking, and building fully schema-driven forms connected to a backend — worth checking out if you want a comprehensive reference rather than piecing together blog posts.
Observation history
See 2 earlier observations
Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.
How did Obsurfable measure this prompt?
Obsurfable records AI answers to buyer-style prompts in its research corpus (3 observations for this page). Metrics are distributions over observations, not a single static ranking.
Which AI systems does Obsurfable collect answers from?
OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.