Vue.js simplifies working with forms using the v-model directive. Let’s explore how to bind form inputs to reactive properties using this directive, handle form submission, and efficiently work with user inputs.
Setting Up Reactive Properties
The first step in working with forms is creating a reactive property that will store form data. In Vue.js, you can use ref or reactive to define a reactive object that will contain form data.
const formData = ref({
  name: '',
  password: '',
  age: '',
  checked: false,
});
This formData object will serve as a data store for form inputs.
Creating a Basic Form
Let’s create a simple registration form containing various types of input fields. Notice the use of v-model on each input. This directive binds the form fields to the corresponding property in the formData object.
<form @submit.prevent="submitForm">
  <label for="name">Name: </label>
  <input type="text" id="name" v-model.trim="formData.name">

          <label for="password">Password: </label>
          <input type="password" id="password" v-model="formData.password">

          <label for="age">Age: </label>
          <input type="text" id="age" v-model.number="formData.age">

          <input type="checkbox" v-model="formData.checked">
          <button type="submit">Submit</button>
      </form>
In this form, we attach an event handler for form submission. Instead of using e.preventDefault(), we use submit.prevent, which achieves the same result.
Handling Form Submission
To process form data, we define a method called submitForm that logs or sends the data.
function submitForm() {
  console.log(formData.value);
  console.log(typeof formData.value.age); // number
}
Thanks to v-model.number, the type of formData.value.age is automatically a number instead of a string.
Using Modifiers with v-model
Vue.js offers modifiers that extend the functionality of v-model:
  • number: Automatically converts input values to numbers.
  • trim: Removes leading and trailing spaces from input values.
<input type="text" v-model.number="formData.age">
<input type="text" v-model.trim="formData.name">
These modifiers simplify handling input data without the need for additional processing.
Working with Checkboxes
Checkbox inputs are bound to boolean values using v-model.
<input type="checkbox" id="terms" v-model="formData.checked">
<label for="terms">I agree to the terms</label>
The value of formData.checked updates to true or false depending on whether the checkbox is checked.
Live Feedback
You can provide users with live feedback by displaying reactive properties directly in the template. These values update dynamically as users interact with the form.
<p>Checked: {{ formData.checked }}</p>
Complete Example
For clarity, here is the full example:
<!DOCTYPE html>
<html>
<head>
  <title>Vue.js Tutorial</title>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <meta charset="utf-8">
</head>
<body>
<div id="app">
  <form @submit.prevent="submitForm">
      <p>
          <label for="email">Email: </label>
          <input type="email" id="email" v-model.trim="formData.email">
      </p>

      <p>
          <label for="password">Password: </label>
          <input type="password" id="password" v-model.trim="formData.password">
      </p>

      <p>
          <input type="checkbox" v-model="formData.checked">
      </p>

      <p>
          <label for="age">Age: </label>
          <input type="text" id="age" v-model.number="formData.age">
      </p>

      <button type="submit">Submit</button>
  </form>
</div>
<script>
  const { createApp, ref } = Vue;

  createApp({
      setup() {
          const formData = ref({
              email: '',
              password: '',
              checked: false,
              age: "",
          });

          function submitForm() {
              console.log(formData.value);
              console.log(typeof formData.value.age);
          }

          return {
              formData,
              submitForm,
          }
      },
  }).mount("#app");
</script>
</body>
</html>