Using Vue.Js to link a value to a checkbox within a component

I'm currently developing a custom component that wraps around a checkbox (similar to what I've done with text and number input types), but I'm facing an issue with binding the passed-in value correctly.

Here's the structure of my component:

<template>
  <div class="field">
    <label :for="name" class="label">
      {{ label }}
    </label>
    <div class="control">
      <input :id="name" :name="name" type="checkbox" class="control" :checked="value" v-on="listeners" />
    </div>
    <p v-show="this.hasErrors" class="help has-text-danger">
      <ul>
        <li v-for="error in errors" :key="error">{{ error }}</li>
      </ul>
    </p>
  </div>
</template>
<script>
export default {
  name: 'check-edit',
  props: {
    value: {
      type: Boolean,
      default: false
    },
    label: {
      type: String,
      default: ''
    },
    name: {
      type: String,
      default: ''
    },
    errors: {
      type: Array,
      default: () => []
    }
  },
  mounted () {
  },
  computed: {
    listeners () {
      return {
        // Pass all component listeners directly to input
        ...this.$listeners,
        // Override input listener to work with v-model
        input: event => this.$emit('input', event.target.value)
      }
    },
    hasErrors () {
      return this.errors.length > 0
    }
  },
}
</script>

I have globally imported this component and used it in another view like this:

<check-edit name="ShowInCalendar" v-model="model.ShowInCalendar" label="Show in calendar?" :errors="this.errors.ShowInCalendar"></check-edit>

The data model contains the property ShowInCalendar, which is a boolean. In my test case, it is set to true. When I view the page, the checkbox is checked as expected. However, when I interact with the checkbox, the value changes to 'on' and subsequent changes do not reflect on the ShowInCalendar model property.

I came across this example here and attempted to implement a local data property, but it didn't resolve the issue.

In essence, I aim to initialize the checkbox based on the ShowInCalendar property bound via v-model and update the property accordingly when the checkbox state changes. Any advice or suggestions would be greatly appreciated.

Thank you.

Answer №1

Avoid using $emit event.target.value as it will only return the value of the checkbox, not a Boolean value. To accurately determine if the checkbox has been updated to true or false, use $emit event.target.checked as suggested by fstep.

Answer №2

If you find that v-on is the sole listener being used, it may be more convenient to utilize v-model as demonstrated in the checkbox example provided in the Vue input documentation.

Nevertheless, alternative listeners can be implemented based on the guidelines outlined in the Binding Native Events to Components documentation.

<template>
  <div class="field">
    <label :for="name" class="label">
      {{ label }}
    </label>
    <div class="control">
      <input :id="name" :name="name" type="checkbox" class="control" checked="value" v-on="listeners" />
    </div>
    <p v-show="this.hasErrors" class="help has-text-danger">
      <ul>
        <li v-for="error in errors" :key="error">{{ error }}</li>
      </ul>
    </p>
  </div>
</template>
<script>
export default {
    name: 'check-edit',
    props: {
        value: {
            type: Boolean,
            default: false
        },
        label: {
            type: String,
            default: ''
        },
        name: {
            type: String,
            default: ''
        },
        errors: {
            type: Array,
            default: () => []
        }
    },
    mounted() {},
    computed: {
        listeners() {
            var vm = this;
            // `Object.assign` merges objects together to form a new object
            return Object.assign(
                {},
                // We add all the listeners from the parent
                this.$listeners,
                // Then we can add custom listeners or override the
                // behavior of some listeners.
                {
                    // This ensures that the component works with v-model
                    input: function(event) {
                        vm.$emit('input', event.target.checked);
                    }
                }
            );
        },
        hasErrors() {
            return this.errors.length > 0;
        }
    }
};
</script>


Answer №3

Avoid modifying props directly. Instead, your component that utilizes a v-model should trigger input events when changes occur. The parent component will be responsible for updating the value accordingly.

Answer №4

Sends information from a checkbox input to its parent.

(Implemented in Vue3 using Script setup and Typescript)

Parent component utilized

<script setup lang="ts">

import { ref } from 'vue'
import Triline from './Triline.vue'

const isChecked = ref(false)

</script>

<template>
    <div style="color: aliceblue;">
       <Triline @on-checked="isChecked=$event"/>
       {{isChecked}}
    </div>
</template>

Method 1:

const checkedo:: is not necessary.

Using @input instead of @change and .value instead of .checked is the correct approach for handling checkbox inputs (referencing the first paragraphs).

Triline.vue component

<script setup lang="ts">

import { ref} from 'vue'

const checkedo= ref(false);

const emit = defineEmits<{
(e:"onChecked",v:boolean):void}>()

</script>

<template>
    <div class="triline">
  
        <input type="checkbox" id="checkbox"
        :value="checkedo"
        @change="$emit('onChecked',checkedo =($event.target as HTMLInputElement).checked)"
        >
        <label for="checkbox">{{ checkedo }}</label>
    </div>
</template>

Method 2 (using watch):

const checkedo is necessary for the watch feature.

Using @input over @change and .value over .checked follows the recommended practices for handling checkbox inputs (referencing the first paragraphs).

Triline.vue component

<script setup lang="ts">

import { ref, watch } from 'vue'

const checkedo= ref(false);

const emit = defineEmits<{
(e:"onChecked",v:boolean):void}>()

watch(checkedo, () => {
      emit("onChecked", checkedo.value);
})

</script>

<template>
    <div class="triline">
  
        <input type="checkbox" id="checkbox"
        :value="checkedo"
        @change="event => checkedo=(event.target as HTMLInputElement).checked"
        >
        <label for="checkbox">{{ checkedo }}</label>
    </div>
</template>

Method 3:

const checkedo is required for the watch functionality.

Utilizing @input instead of @change and .value instead of .checked aligns with best practices for managing checkbox inputs (referring to the initial paragraphs).

Triline.vue component

<script setup lang="ts">

import { ref, watch} from 'vue'

const checkedo= ref(false);

const emit = defineEmits<{
(e:"onChecked",v:boolean):void}>()

watch(checkedo, () => {
      emit("onChecked", checkedo.value);
})

</script>

<template>
    <div class="triline">
  
        <input type="checkbox" id="checkbox"
        v-model="checkedo"
        >
        <label for="checkbox">{{ checkedo }}</label>
    </div>
</template>

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

Tips for creating visually appealing text on a web browser with the help of open-source libraries

Have you ever noticed that no matter how we display text on webpages, whether it's in a <p> tag or an <h1> tag, the result is always the same? (a screenshot of a rendering done in Firefox) Do you struggle with pixelated areas on the curv ...

Having trouble with AES decryption on my nodeJS/ExpressJS server backend

Looking to decipher data post retrieval from mongoDb. The retrieved data comprises encrypted and unencrypted sections. app.get("/receive", async (req, res) => { try { const data = await UploadData.find(); const decryptedData = data. ...

Why is the parameter value becoming null during an Ajax call?

I am passing a parameter from HTML to JSP, but when I try to retrieve the value in JSP, it returns null. Can someone help me figure out what's wrong with my code and provide any suggestions? The value is successfully displayed in an alert using JavaS ...

How can you initiate the wizard sequence again in TelegrafJS?

I've created a handler function for "/start" that leads to the wizard scene. Now, I have a message with an inline_keyboard containing a button labeled "redo". When I click on the "redo" button, I want it to restart the entire scene, basically initiat ...

retrieving embedded content from an iframe on Internet Explorer version 7

Need help with iframe content retrieval $('.theiframe').load(function(){ var content = $(this.contentDocument).find('pre').html(); } I'm facing an issue where the iframe content is retrieved properly in FF, Chrome, and IE 8,9 ...

A numerical input field that removes non-numeric characters without removing existing numbers?

Currently, I have implemented the following code: <input type="text" onkeyup="this.value = this.value.replace(/\D/g, '')"> This code restricts users from entering anything other than numbers into a field on my webpage. However, I hav ...

JQuery plugin for creating interactive date selection forms

Having some trouble creating a dynamic form. The datepicker seems to only work on the first row and I can't click it. Tried a few different codes but no luck so far. Below is the code excluding the PHP part, which is just for inserting into a database ...

Ways to pinpoint a particular division and switch its class on and off?

Consider this scenario, where a menu is presented: function toggleHiddenContent(tabClass) { let t = document.querySelectorAll(tabClass); for(var i = 0; i<t.length; i++) { t[i].classList.toggle="visible-class"; } } .hidden-conten ...

Observables do not provide any results when used in a pipe with an image src

I recently created a custom pipe for the image src in my application: It is applied to selectors like this: <img [src]="myobject?.URL | secure" /> Here's the code snippet for the pipe: import { Pipe, PipeTransform } from '@angular/c ...

Wrapping a group of elements with opening and closing tags using jQuery

I have a collection of distinct elements, like so: <section class="box-1"></section> <section class="box-2"></section> <section class="box-3"></section> My objective is to enclose all three elements within a div with a ...

Guidelines for incorporating JS in Framework7

I am developing an application using the framework7. I am facing a challenge where I need to execute some javascript in my page-content, but it is not running as expected. <div class="pages"> <div class="page close-panel" data-page="item"> ...

Not every child within a transition group in Vue.js is currently engaged in animation

This is the specific transition group that I have implemented <article class="hotel-row" v-for="hotel in paginatedHotels" :key="hotel.hotelid"> <search-hotel :hotel="hotel"></search-hotel> </article> If I do not assign unique ...

VueDraggable communicates with the database by sending a request during drag and drop interactions

Help needed with the vuedraggable component. I have three columns (photo attached) and I would like to be able to drag BoardUserCard between the columns. Upon dropping the card, I want to send a PUT request to the database to change the "lead_status_id" as ...

In what ways can I leverage the functionalities of an AngularJS directive to delay the display of content until a user clicks on it?

Our rental application utilizes an API call to populate an array, triggering an ngRepeat and generating a list of divs displaying basic rental property information. Upon clicking a specific property, another API call is made to populate an interior ngRepe ...

Using jQuery idle timeout to abort jQuery AJAX calls in Laravel 5.2

Currently, I have implemented the jQuery Idle Timeout plugin in my Laravel 5.2 system. Everything works perfectly on my local setup using MAMP Pro, but upon uploading it to the development server, I encountered an "Aborted" error in the AJAX get request: ...

NextJS rewrites work seamlessly in a live environment

I recently implemented a method to rewrite requests to my backend server during development: https://nextjs.org/docs/api-reference/next.config.js/rewrites rewrites: async () => [ ...nextI18NextRewrites(localeSubpaths), { source: '/api/:path*' ...

Seems like the ng-show events inside are not being triggered, almost like an invisible image

I am encountering an issue where no JavaScript events are triggering inside an ng-show div in my code. You can access my code through the following link on Plnkr: http://plnkr.co/edit/kGqk8x?p=preview Upon loading data from JSON, I set ng-show to true. Ho ...

position blocks next to each other within a container

Thank you for all the hard work! I've been struggling to figure out how to align blocks next to each other within a div. It may not be that difficult, but I just can't seem to find an elegant solution... Here is the HTML code snippet: <div ...

The local server for handling HTTP requests has ceased to operate

Recently, I set up the NPM package along with the http server within the "server" directory. Initially, everything was functioning smoothly; however, the server abruptly ceased operating. Upon attempting to launch the local http server, an error message a ...

Unexpected Issues with Page Refresh in AngularJS

I am currently working on an Angular application using the MEAN stack. Here's a scenario: imagine you have an express route that queries the database and sends the results back in the response: app.get('/api', function(req, res){ Todo.f ...