Deselect radio option

I am attempting to create a Vue instance with a group of radio buttons. My aim is that when a user clicks on a checked radio button, it will become unchecked. However, I have not been successful in accomplishing this using Vue so far. Below is the code I have written:

HTML:

<div id="app">
    <div v-for="(val, key) in list">
        <input type="radio" name="radio" :value="val" v-model="selected" :id="val">
        <label :for="val" @click="uncheck( val )">{{ val }}</label>
    </div>
    <button @click="uncheckAll">Uncheck all</button>
</div>

JS:

var app = new Vue({
        el: '#app',
        data : {
            list: [ 'one', 'two', 'three' ],
            selected: 'two',
        },
        methods : {
            uncheck: function( val ){
                console.log( val, this.selected );
                if ( val == this.selected ){
                    this.selected = false;
                }
            },
            uncheckAll: function(){
                this.selected = false;
            }
        }
})

It appears that the uncheck method is being called, but then the radio button triggers a change event and updates the value of

selected</code again. The <code>uncheckAll
method works as expected, probably because it does not use v-model.

Do you have any suggestions or tips to make this functionality work? You can view an example of the code on this pen: https://codepen.io/diegoliv/pen/JrPBbG

Answer №1

One challenge is that the v-model is altering the value of selected before you have a chance to assess its previous value. An additional variable is needed.

The concept is as follows: when an item is clicked, it verifies if it matches previouslySelected instead of selected. If there is a match, deselect the item. Then update previouslySelected with the value of selected.

The click function should be on the input rather than on the label; since the label's purpose is to redirect clicks to the input anyway.

var app = new Vue({
  el: '#app',
  data: {
    list: ['one', 'two', 'three'],
    selected: 'two',
    previouslySelected: 'two'
  },
  methods: {
    uncheck: function(val) {
      if (val === this.previouslySelected) {
        this.selected = false;
      }
      this.previouslySelected = this.selected;
    },
    uncheckAll: function() {
      this.selected = false;
    }
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <div v-for="(val, key) in list">
    <input type="radio" name="radio" :value="val" v-model="selected" :id="val" @click="uncheck(val)">
    <label :for="val">{{ val }}</label>
  </div>
  <button @click="uncheckAll">Uncheck all</button>
</div>
Note: the method below is not compatible with Vue 2.5 or newer versions because clicking on an already-selected radio does not trigger a set action. (acknowledgements to Vlad T. from the comments)

An alternative approach would be handling things more data-centrically by creating a computed property based on your selected value and having its setter handle the re-selection check. No need for a click handler. Everything is managed during the normal process of setting the value.

var app = new Vue({
  el: '#app',
  data: {
    list: ['one', 'two', 'three'],
    d_selected: 'two'
  },
  computed: {
    selected: {
      get() {
        return this.d_selected;
      },
      set(v) {
        if (v === this.d_selected) {
          this.d_selected = false;
        } else {
          this.d_selected = v;
        }
      }
    }
  },
  methods: {
    uncheckAll: function() {
      this.d_selected = false;
    }
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <div v-for="(val, key) in list">
    <input type="radio" name="radio" :value="val" v-model="selected" :id="val">
    <label :for="val">{{ val }}</label>
  </div>
  <button @click="uncheckAll">Uncheck all</button>
</div>

Answer №2

Presented here is a straightforward example that does not rely on v-model and simply utilizes one variable to hold the current selected value.

var app = new Vue({
  el: '#app',
  data: {
    list: ['one', 'two', 'three'],
    selected: 'two'
  },
  methods: {
    uncheck: function (val) {
      if (val === this.selected) {
        this.selected = false
      } else {
        this.selected = val
      }
    }
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <div v-for="(val, key) in list">
    <input type="radio" :checked="selected===val" :id="val" @click="uncheck(val)" :key="'input' + key">
    <label :for="val" :key="'label' + key">{{ val }}</label>
  </div>
</div>

Answer №3

To prevent the default behavior of clicking the label, you can utilize the prevent modifier:

<label :for="val" @click.prevent="uncheck( val )">{{ val }}</label>

If you want to see a functioning example, check out this Codepen: Link

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

Dealing with transformed data in AngularJS: Best practices

Scenario I have a dataset structured like: [{ xRatio: 0.2, yRatio: 0.1, value: 15 }, { xRatio: 0.6, yRatio: -0.3, value: 8 }] I need to convert this data into absolute values for display in a ng-repeat. However, when I attempt to do so usin ...

What is the method for obtaining the input value of an input type number in HTML?

Within my form, there is a number field where users can input scores: <input type="number" min="0" max="100" class="form-control" name="total_score" id='total_score' value="<?php echo $total_score;?>" >(Please input a score from 0-10 ...

Toggle the visibility of a div by clicking on another div in a

I have created a unique design where a div features a background image of a face, along with a paragraph, two buttons, and an input box inside it. While I know this question has been asked before, my scenario is slightly different. I want the div with the ...

Error encountered while trying to call callback functions

I encountered an error in my code, but I managed to resolve it independently. Could someone please provide an explanation of why the code wasn't working and delve into the mechanics behind the issue? Here is the code snippet: var listTables = functi ...

Is there a way to store the JWT response header retrieved with fetch?

I am currently utilizing React and employing fetch to send a request to the server: fetch("http://localhost:8001/api/login", { method: 'post', headers: { "Content-type": "application/x-www-form-urlencoded; charset=UTF-8" }, ...

Ways to verify audio in several HTML5 video files

I am working on a way to determine if multiple videos have audio or not. Here is an example of what I have so far: https://jsfiddle.net/hrd4a0c3/ However, my current solution only checks one video at a time. I am looking for a way to extend this functiona ...

Decoding multiple data with jQuery on the server-side

Scenario: A situation arises where I am utilizing a jQuery.ajax call to send three arrays to the server for database storage. The challenge lies in decoding the combined data object on the server side and breaking it back into the original three arrays. ...

Having trouble with the JQuery class selector?

Having a bit of trouble trying to select an element based on its class using $(".class"), and I can't seem to figure out why it's not working. So, the deal is - I have this image element that should appear when a function gets triggered: $("#co ...

Implementing Event Listeners in Vue 3.0: A Guide to Attaching to the Parent Element

How can I attach an addEventListener to the parent element in Vue 3.x? I discovered that you can access the parent by using this code: import { getCurrentInstance, onMounted } from 'vue' onMounted(() => { console.log(getCurrentInstance() ...

Issue with dropdown list functionality in Internet Explorer not functioning correctly

I am experiencing an issue with my dropdown lists. When selecting an item from the first dropdown list, it should not be available in the second dropdown list. To achieve this functionality, I have implemented jQuery code like the following: $(document).r ...

Is invalid HTML causing issues with Backbone.js templating in Phonegap?

Summary: When my template file contains valid HTML code, it does not display in Phonegap. The structure of my index.html file is as follows: <body onload="onBodyLoad()"> <div data-role="page"> <a href="#login" id="clickme">C ...

Activate the textbox without utilizing `.focus()` method

I am encountering an issue with a small iframe on my page. The content within the iframe is larger than the window itself, requiring users to scroll around to view it in its entirety. Within this iframe, there is a button that, when clicked, triggers an an ...

Having trouble resolving '@auth0/nextjs-auth0' during deployment on Vercel? Check out this error message: "Can't resolve '@auth0/nextjs-auth0' in '/vercel/path0/pages'"

I recently deployed a project on Vercel and have been working on enhancing the layout to achieve a minimum viable product (MVP). As part of this process, I decided to switch my authentication method to @auth0/nextjs-auth0 package for Next.js. After running ...

Enabling hover effects to scroll divs only when interacted with

I am aiming to achieve two separate scrolling divs and I'm uncertain about the exact approach. Experimenting with various overflow properties has only resulted in one scrolling independently. .profile { width: 100%; display: flex; ...

Confirming the username's accuracy through an external API as part of the registration procedure

My latest project involves creating a web application specifically for Fortnite players looking to connect with other gamers. The concept is simple: users can register, log in, post, and comment within the platform. I have successfully designed the fronten ...

Error in Internet Explorer 8 - the object does not support this property or method

My ExtJS custom "treecombo" works perfectly in Firefox and Chrome, but encounters issues in Internet Explorer. Specifically, I am facing problems with IE8 when trying to run the following code: Ext.define('MyApp.plugins.TreeCombo', { extend: & ...

Firestore query failing to retrieve most recent data

I have implemented a route guard in Angular that validates a specific value in firestore before granting access to the designated route. The component is accessed only after an HTTP cloud function has finished executing. This cloud function generates an o ...

Updating a Nested Form to Modify an Object

There is an API that fetches an object with the following structure: { "objectAttributes": [ { "id": "1", "Name": "First", "Comment": "First" }, { "id": "2", "Name": "Second", "Comment": "Second" } ] ...

Error encountered in production mode - TypeError: o is not a function in Vue/webpack/Laravel Mix

Good day. I am utilizing Vue 2 alongside Laravel Mix/Webpack and Node version 14.18.1. Running 'npm run dev' works perfectly fine for me. However, when I execute 'npm run production', I encounter an error saying: TypeError: o is not a ...

What is the significance of the exclamation point before and after in JavaScript?

Currently collaborating on a project and attempting to decipher the significance of the exclamation marks both before and after. import ICHING from '!json!constants/iching_deoxy.json'; ...