How to Build Configurable, Dynamic Forms in Vue.js

This article explains how to create flexible, schema‑driven web forms using Vue.js, covering requirements definition, backend data injection, component architecture, functional controls, event handling, and validation logic to replace traditional server‑rendered forms.

Baixing.com Technical Team
Baixing.com Technical Team
Baixing.com Technical Team
How to Build Configurable, Dynamic Forms in Vue.js

Background

Forms are the earliest logical part of modern web pages and remain crucial for blog, classified, and forum sites where user‑generated content is central. Traditional server‑side rendering of forms struggles with complex interactions such as real‑time validation and inter‑field dependencies, prompting a shift to MVVM patterns popularized by WPF and Knockout and now fully embraced by Vue.js.

Goal

The article outlines several concrete requirements for a simple form:

A form with three fields: content, address, and contact.

The content field must be at least eight characters and reject certain prohibited phrases.

The address field should be a tree‑select allowing province‑to‑district selection.

The contact field is mandatory and must be a mobile number.

If the content contains a phone number and the contact field is empty, the number should be auto‑filled into the contact field.

While basic constraints can be handled with HTML5 required or pattern, more complex logic requires JavaScript.

<form class="form">
  <div class="form-line">
    <div class="form-control">
      <textarea name="content"></textarea>
    </div>
  </div>
  ...
  <button type="submit">提交</button>
</form>

Ideally, a configuration should generate this structure and its logic automatically.

[
  {"type":"textarea","name":"content","validators":["minlength":8]},
  {"type":"tree","name":"address","datasrc":"areaTree","level":3},
  {"type":"text","name":"contact","required":true,"validators":["regexp":"<mobile>"]}
]

Implementation

Vue.js is used to build the form. The backend passes a JSON schema and a context object via <script type="text/json" ref="schema"> and <script type="text/json" ref="context"> tags, which are parsed in the Vue instance:

new Vue({
  mounted() {
    this.schema = JSON.parse(this.$refs.schema.innerText);
    this.context = JSON.parse(this.$refs.context.innerText);
  }
});

The my-form component renders the form based on the schema:

<template>
  <form :class="form" method="post">
    <my-line v-for="(item, index) in schema" :schema="item"></my-line>
  </form>
</template>

Each line delegates to a functional my-control component that selects the appropriate control type:

export default {
  functional: true,
  props: { schema: Object },
  render(h, context) {
    return h(getControl(context), context);
  }
};

Common logic such as display name and data handling is abstracted into a mixin ( contract.js) and shared across controls:

export default {
  computed: {
    displayName() {
      return this.schema.displayName || this.schema.name;
    }
  }
};

An event‑emitter core ( Core) provides a unified way to listen for and emit form and control events, enabling validation rules like required fields and conditional checks (e.g., auto‑filling contact when a phone number appears in content).

Core.form().on('update', function(control) {
  if (!control.schema.required) return;
  if (control.model) {
    Core.form().emit('resolve-error', control, 'required');
  } else {
    Core.form().emit('reject-error', control, 'required', '此项必填');
  }
});

Slots are used to inject external elements such as submit buttons or CSRF tokens without treating them as form controls.

Conclusion

Vue.js’s two‑way binding, component model, and template system make form development highly modular and maintainable. By describing forms with a JSON schema and leveraging reusable components, developers can handle complex validation, dynamic field generation, and business logic separation more efficiently than with traditional server‑rendered approaches.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Dynamic FormsComponent ArchitectureVue.jsform-validation
Baixing.com Technical Team
Written by

Baixing.com Technical Team

A collection of the Baixing.com tech team's insights and learnings, featuring one weekly technical article worth following.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.