Using Vue3 to Enable or Disable the Submit Button Based on Changes in Editable Form Content

Here is a practical example, demonstrating how to create an editable address form.

The save button should remain disabled if the form remains unchanged, as there is no need to submit it. However, when a value changes, the save button should become enabled.

In Vue 3, what would be an effective method to achieve this? In a real-world scenario with a large form and numerous input fields listed similarly below, using a watcher for each individual value may not be ideal.

Grouping all the data values into a single form data object could allow you to utilize a deep watcher, although this approach may lack efficiency.

Another consideration is that when the user initially views the form, the first name is 'john' and the save button is disabled. If the user modifies 'john' to 'johnn', the button should then become enabled. Conversely, reverting the value from 'johnn' back to 'john' should disable the button again as the form returns to its original state.

One potential solution involves establishing an initial value for each form input with v-model, such as:

Vue.createApp({
  data() {
    first_name: 'john',
    initial_first_name: 'john'
  }
})

However, implementing this concept efficiently in a substantial form with multiple fields can be challenging, especially if you're unfamiliar with the process.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Home</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <script src="https://unpkg.com/vue@3/dist/vue.global.js" defer></script>
    <style>
      .submit-btn {
        color: #fff;
        background: #000;
        padding: 24px;
      }

      .submit-btn[disabled] {
        color: #fff;
        background: #999;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <form @submit="onSubmit" id="test-form">

        <label for="first_name">First Name</label>
        <input id="first_name" 
          type="text"
          v-model="first_name"
        >

        <label for="email">Email</label>
        <input id="email" 
          type="email"
          v-model="email"
        >

        <input type="submit" 
          value="save" 
          class="submit-btn"
          :disabled=""
        >
      </form>
    </div>

    <script type="module">
      Vue.createApp({
        name: 'form_app',
        data() {
          return {
            first_name: 'john',
            email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="167c797e7856717b777f7a3875797b">[email protected]</a>'
          }
        },
        methods: {
          onSubmit(e) {
            e.preventDefault()

            console.log('form submitted')
          }
        }
      }).mount('#app')
    </script>
  </body>
</html>

Answer №1

To make a reactive object with the form data, you can utilize the reactive function and then implement a computed property to ascertain if the form has been altered.

Here is an illustration:

<template>
  <form>
    <label for="first_name">First Name</label>
    <input id="first_name" type="text" v-model="form.first_name">

    <button type="submit" :disabled="formUnchanged">Save</button>
  </form>
</template>

<script>
import { reactive, computed } from 'vue';

export default {
  setup() {
    const form = reactive({
      first_name: 'John',
    });
    const initialForm = JSON.stringify(form);

    const formUnchanged = computed(() => {
      return JSON.stringify(form) === initialForm;
    });

    return { form, formUnchanged };
  },
};
</script>

You can employ reactive to generate a dynamic form object containing the form data, and use computed to produce a formUnchanged attribute that verifies whether the form object has altered since its initial state.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a feature in Angular similar to Vue.js's "computed property" functionality?

After mastering Vue.js, I recently dove into Angular 4 for a new project. I've found that most things in Angular are quite similar to Vue, with the notable exception of "Computed Property". In Vue, I could easily create a computed property that would ...

Is there a way to automatically advance to the next question in Surveyjs without needing to click the Continue

I'm currently integrating SurveyJs into my web application. The first 3 pages of my survey contain HTML elements that I would like to automatically slide after a few seconds, similar to the functionality on the following sample site using SurveyJS: O ...

Using vue-router within a pinia store: a step-by-step guide

I'm currently setting up an authentication store using Firebase, and I want to direct users to the login/logged page based on their authentication status. My goal is similar to this implementation: https://github.com/dannyconnell/vue-composition-api- ...

Enabling or disabling select input based on the selected option in a previous select dropdown

My goal here is to customize a select input with 3 options: Sale, Rent, Wanted. Based on the selection, I want to display one of three other select inputs. For example, if "Sale" is chosen, show the property sale input and hide the others. However, when su ...

The failure to parse an object in response to a JavaScript AJAX call

Why am I getting undefined in the console? Javascript code: var url = "/SitePages/AlertsHandler.aspx/GetAlert"; $.ajax({ type: "POST", url: url, data: '{alertId: \"' + alertId + '\"}', contentType: "applicati ...

Adjust the height of the Iframe to match the content within it

After conducting my research, I have not been able to find a solution. Although I am not an expert in jQuery, it seems that the code is not functioning properly. Within the iframe are links that expand when clicked to display content. However, the height o ...

Incorporating CouchDB storage into a Node.js socket.io JSON data stream

Currently in the process of researching how to implement persistence for a real-time Twitter JSON feed in Node.js. The stream is set up and sending data to the client, but I'm struggling with storing this information in a CouchDB database so that it c ...

JavaScript Transformation of Date Format

var dt="29/05/2013"; //DD/MM/YYYY I am looking to change the format to yyyy/MM/dd; My current approach is: var newdate=dt.getFullYear()+"/"+dt.getMonth()+"/"+dt.getDate(); Is there a more straightforward way to convert it without using substring? No p ...

Unable to observe the transition of opacity changes in threeJS for tweens

<script type="importmap"> { "imports": { "three": "https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f2869a809797b284c2dcc3c4c0dcc2">[email protected]& ...

Discovering the number of intervals running at any given time within the console - JavaScript

I'm having trouble determining if a setInterval() is active or has been cleared. I set up an interval and store it in a variable: interval = setInterval('rotate()',3000); When a specific element is clicked, I stop the interval, wait 10 sec ...

What is the best way to supply JSON data to the "The Wall" MooTools plugin while feeding?

I came across this amazing plugin called "The Wall" but unfortunately, neither the documentation nor the examples demonstrate how to utilize JSON objects with it. Imagine we have a JSON array like: [ { href : "/my/photo/image1.jpg", title : "Me an ...

AngularJS filtering with multiple conditions

My ng-repeat list is currently displaying a collection of objects with a filter applied to only show objects inserted today. Here is how it looks: <div class="row msf-row" ng-repeat="record in recordlist | filter: record.date = dateJson"> Whi ...

Issues with merging styles in TinyMCE 4

I've exhausted all the current configuration options and I'm still unable to resolve this issue. My goal is to have the style tag appended to the selected element without generating an additional span. For example: <p>Hello World!</p> ...

Is it possible to resize an object using JavaScript?

Is it possible to change the size of an object when loading specific data by clicking on navigation? <object id="box" width="250" height="250" data=""></object> Although the JS code loads the data, it does not change the size. document.getEl ...

The Vue-Material navbar is indicating an essential prop is missing: "to"

According to the Vue-Material documentation, it is possible to create a md-bottom-bar filled with md-bottom-bar-item that can act like a <router-link>. The code snippet provided by them can be found under "Seamless integration with Vue Router", and ...

Is it possible to use a global mixin alongside an imported one in Vue?

Alright, so I'm working on a Vue 2 project and I have set up a global mixin. Take a look at the code snippet below: import Vue from "vue"; import App from "./App"; import router from "./router"; import store from "./ ...

Personalize your material-ui popover

Seeking assistance in customizing the shape of a material-ui popover similar to the one depicted in the image. https://i.sstatic.net/l5uNL.png I have created a working demo of the popover using React and provided a link for editing purposes. Any help? =& ...

Discover the power of React Meteor, where reactive props and inner state work together

I am working with a component that utilizes the draft-js library for text editing. import React, { Component } from 'react' import { EditorState, convertToRaw } from 'draft-js' import { Editor } from 'react-draft-wysiwyg' imp ...

Error encountered while parsing data in Internet Explorer versions 7, 8, 9, and 10 due to an invalid character. The status

This block of code is functioning correctly on Chrome and Firefox, however it seems to be having issues with Internet Explorer! It involves a simple JSON file call, fetching data, and then displaying it on an HTML webpage. Here's the code snippet: $. ...

Combining Wordpress with Vue and Nuxt for seamless integration: Enhancing your website with wp_enqueue_script

I am in the process of updating my existing website by gradually replacing the html/css interfaces with Vue technology. As a result, I now have pages that feature two different logics: Pages that are fully developed using vue Pages that consist of both ht ...