How to activate a button only if the specified conditions are met using VueJS 3

I'm currently facing challenges while working on a form to enable a button when certain conditions are met.

The form I created includes fields for name, phone number, options, and a message. Once all requirements are filled, I aim to re-enable the disabled submit button.

Any advice on how to successfully re-enable the button for form submission?

<template>

    <div class="contact">
  <h1>We appreciate all questions you may have regarding this application!</h1>
  <h2>Please leave a message below, and we will do our best to respond promptly!</h2>
</div>

  <form @submit.prevent="submitForm">
    <div class="form-control" :class="{invalid: fullNameValidation === 'invalid'}">
      <label for="name">Name</label>
      <input id="name" name="name" type="text" v-model="fullName" @blur="validateInput">
      <p v-if="fullNameValidation === 'invalid'">Please enter your name.</p>
    </div>
    <div class="form-control" :class="{invalid: phoneValidation === 'invalid'}">
      <label for="phone">Phone Number</label>
      <input id="phone" name="phone" type="number" v-model="phoneNr" @blur="validatePhone" pattern="[0-9]*">
      <p v-if="phoneValidation === 'invalid'">Please enter a valid phone number.</p>
    </div>
    <div class="form-control">
      <label for="referrer">How did you hear about this application?</label>
      <select id="referrer" name="referrer" v-model="referrer">
        <option value="" disabled hidden>Select an option</option>
         <option value="internet">Internet</option>
        <option value="friends">Friends</option>
        <option value="newspaper">Newspapers</option>
        <option value="other">Other</option>
      </select>
    </div>
    <div class="form-control" :class="{invalid: messageValidation === 'invalid'}">
      <label for="message">Message</label>
      <textarea name="message" id="message" cols="30" rows="10" v-model="message" @blur="validateMessage"></textarea>
       <p v-if="messageValidation === 'invalid'">Please enter your message.</p>
    </div>

    <div>
      <button v-on:click="$router.push('thankyou')" :disabled="!isComplete" id="myBtn">Send Message</button>
    </div>
  </form>
</template>

<script>
export default {
    data() {
        return {
            fullName: '',
            fullNameValidation: 'pending',
            phoneNr: 'null',
            phoneValidation: 'pending',
            referrer: '',
            messageValidation: 'pending'
        }
    },

    methods: {
        submitForm() {
            this.fullName = '';
        },
        validateInput() {
            if (this.fullName === '') {
                this.fullNameValidation = 'valid'
            } else {
               this.fullNameValidation = 'invalid'
            }
        },
        validatePhone() {
           if (this.phoneNr > 10) {
                this.phoneValidation = 'valid'
            } else {
                this.phoneValidation = 'invalid'
            }
        },
         validateMessage() {
            if (this.messageValidation > 1) {
                this.messageValidation = 'valid'
            } else {
                this.messageValidation = 'invalid'
            }
        },

        computed: {
       isComplete() {
          return Object.values(this.fields).every(({valid}) => valid)
      }
  }
    }
}
</script>

Answer №1

Combine all your form fields into one model, including the errors object.

Then utilize Object.keys to access known field keys for validation purposes.

export default {
  data() {
    return {
      form: {
        errors: {},
        values: {
          fullName: '',
          phoneNr: '',
          referrer: '',
        }
      }
    }
  },
  methods: {
    validate(field) {

      let fields = []
      // single field
      if (field) {
        delete this.form.errors[field]
        fields.push(field)
      } else {
        this.form.errors = {}
        // all fields
        fields = Object.keys(this.form.values)
      }


      if (fields.includes('fullName')) {
        if (this.form.values.fullName === '') {
          this.form.errors.fullName = 'Enter your full name'
        } else if (this.fullName !== some other validation) {
          ...
        }
      }

      if (fields.includes('phoneNr')) {
        if (this.form.values.phoneNr === '') {
          this.form.errors.phoneNr = 'Enter your phone number'
        }
      }

      if (fields.includes('referrer')) {
        if (this.form.values.referrer === '') {
          this.form.errors.referrer = 'Enter referrer'
        }
      }

      // if errors is empty return true
      return !Object.keys(this.form.errors).length
    },
    submit() {
      // validate all
      if (this.validate()) {
        // do some thing, form is valid, if native form handler, return true/false
      }
    }
  }
}
<div class="form-control" :class="{invalid: form.errors.fullName}">
  <label for="name">Name</label>
  <input id="name" type="text" v-model="fullName" @blur="validate('fullName')">
  <p v-if="form.errors.fullName">{{ form.errors.fullName }}</p>
</div>

If you don't specifically need the @blur validation, it simplifies things quite a bit and its pretty standard to do validation on submit rather than on blur of individual fields.

export default {
  data() {
    return {
      form: {
        errors: {},
        values: {
          fullName: '',
          phoneNr: '',
          referrer: '',
        }
      }
    }
  },
  methods: {
    validate() {

      this.form.errors = {}

      if (this.form.values.fullName === '') {
        this.form.errors.fullName = 'Enter your full name'
      } else if (this.form.values.fullName !== some other validation) {
        ...
      }

      if (this.form.values.phoneNr === '') {
        this.form.errors.phoneNr = 'Enter your phone number'
      }


      if (this.form.values.referrer === '') {
        this.form.errors.referrer = 'Enter referrer'
      }


      // if errors is empty return true
      return !Object.keys(this.form.errors).length
    },
    submit() {
      if (this.validate()) {
        // do something, form is valid, if native form handler, return true/false
      }
    }
  }
}
<div class="form-control" :class="{invalid: form.errors.fullName}">
  <label for="name">Name</label>
  <input id="name" type="text" v-model="fullName">
  <p v-if="form.errors.fullName">{{ form.errors.fullName }}</p>
</div>

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

The battle between Hover, Focus, and Blur modes intensifies

My goal is to implement 4 different effects on an element: When hovering over the element. When moving away from the element. When focusing on the element. When blurred. However, I'm encountering a conflict where when I focus on the element, the ...

Sending a C# variable to an HTML file

I’m struggling to understand how I can use jQuery to access a variable from C# named sqlReq. My main objective is to be able to input my own SQL data into a PieChart. However, I’m unsure about how to call and define C# SQL requests in HTML or jQuery. ...

Storing notes using HTML5 local storage

I recently developed a unique note-taking web application where users can create multiple notes and switch between them using tabs on the left side. My next step was to implement local storage for saving these notes, so I inserted the following code: $(d ...

Retrieving items from an array based on their class association

My challenge involves handling a list of items obtained using the following code: var searchResultItems = $(resultContainerId + ' li'); Each item in the search results can have different classes. How can I extract all items with a specific clas ...

Printing incorrect value in $.ajax call

I came across this code that I have been working on: var marcas = { nome: '', fipeId: '' }; var marcasVet = []; var select; $.ajax({ dataType: "json", url: 'http://fipeapi.wipsites.co ...

What is the process for incorporating Web Assembly scripts into a React Native application?

I find myself wondering if this task is even feasible. If it is doable, I suspect we'll have to utilize WebViews, but maybe I'm just being overly analytical. Attempted to research this topic, but unfortunately, came up empty-handed. ...

Using a div in React to create a vertical gap between two React elements

I am working with two React Components in my project - the Right Column and the Left Column. I am trying to create space between them using a div tag. Currently, my setup in the App.js file looks like this: import React from 'react'; import LeftC ...

Assistance with the Chakra UI Range Slider in React

I could use some help figuring out where exactly to implement my OnChange and Map functions for mapping JSON data into a Range Slider. Everything seems to be rendering correctly, but I keep encountering an error when I try to move the slider: Unhandled Ru ...

Is it safe to utilize an AngularJS filter for parsing a URL?

When working on a web application, my client-side (angularjs based) receives JSON data from a web service. The JSON can contain a text field with some URLs, such as: blah blah ... http://www.example.com blah blah blah ... To render these links as HTML, I ...

Executing the npm run test command with the unsafe-perm flag within the lifecycle phase

My React/Redux app is working fine, but whenever I run the command below: npm run test An error occurs as shown below: 6 info lifecycle [email protected]~test: [email protected] 7 verbose lifecycle [email protected]~test: unsafe-perm in li ...

Next.js 13 React Server Component not displaying updated data upon build completion

I have a React Server Component that retrieves its data at build time and does not reload it while the site is running. I expected it to fetch the data once when the server component is first rendered. Is there a way to force this server component to relo ...

Is there a way to automatically refresh my log instead of having to do it manually every time?

Currently, I have a log box that displays the logs from my backend. There is a button to manually refresh the log and view the latest set of logs. However, I am looking to implement an auto-refresh feature for the log. How can I achieve this? Below is the ...

The Node.js POST request is unexpectedly returning 'undefined'

I'm currently working on a project for an online course and I'm encountering an issue with making an API call. It seems that I am getting undefined responses to my post request because the user input is not being retrieved properly. Below are the ...

Implement a CSS style for all upcoming elements

I'm currently developing a Chrome extension tailored for my personal needs. I am looking to implement a CSS rule that will be applied to all elements within a certain class, even if they are dynamically generated after the execution of my extension&ap ...

Submitting an HTTP POST REQUEST with both an image and text

Is there a way to send an image with text from VueJs to an ExpressJs backend? I've currently implemented two HTTP POST requests for this process. Please note: "this.albumName" and "this.albumDesc" contain text, while the formData variable holds the ...

Retrieve the route from a specific node in the jstree structure

Looking to retrieve the paths of selected nodes in jstree? You'll need the complete path of the nodes. I have a php file that generates the JSON, structured like this: header("Content-Type: application/json; charset=utf8"); echo json_encode(dir_to_ ...

Uncertainties surrounding the use of JSON data versus a JavaScript object

As a newcomer to programming, I have ventured into Stack Overflow and W3schools to enhance my skills. Recently, I created a small project for educational purposes. One dilemma is bothering me - is the JSON file I generated actually in proper JSON format o ...

React - Page Loads with Empty Query Parameters

Seeking assistance with navigation logic in React, I'm encountering an issue that requires some guidance. I have developed a front-end web app using TypeScript, React, and Ionic Framework V5. The app features a standard search box that redirects use ...

Bringing an AMD module into a Mocha test

I recently encountered an error while using Mocha to test code that was exported as an AMD module. When running the Mocha test, I received the following error message: ReferenceError: define is not defined at Object.<anonymous> (/home/malintha/proje ...

Encountered an error while parsing a module in React: Unexpected token

After deciding to incorporate the npm package react-radio-buttons into my project, I encountered an error upon installation and implementation in my component: ./node_modules/react-radio-buttons/index.jsx 80:6 module parse failed: Unexpected token (80:6) ...