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

Is the reference to a variable within an array maintained by JavaScript?

I'm working with react code and using the find() method to select an item from an array. When I retrieve an item from the array, is JavaScript copying the item or returning a reference? EDIT: The items in my array are objects, such as [{id: 12, name ...

Mastering the art of crafting form elements with jQuery

My code is looking like this: <!DOCTYPE html> <html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> function afterText() { var textElement = document.create ...

What could be causing the sporadic functionality of my jQuery image resizing code?

Seeking help for an issue I am facing with my jQuery code. I have been trying to scale a group of images proportionally within an image carousel using jCarousel Lite plugin. However, the resizing code seems to work randomly and I can't figure out why. ...

How does NodeJs handle ongoing tasks and processes seamlessly?

One interesting concept is the Event Loop, which accepts callbacks and executes them as needed. As far as I understand, this operates on a single thread event loop, meaning only one callback is executed at a time. Consider the following example: setInterv ...

Prevent Purchase Button & Implement Modal on Store Page if Minimum Requirement is not Achieved

On my woocommerce shop page, I am facing an issue where all items are added to the mini-cart without meeting the minimum order requirement. This results in users being able to proceed to checkout without adding enough items to meet the minimum order amount ...

Having trouble importing images in React and passing them as a prop?

I'm attempting to import images, place them into an array, and then pass that array to a prop in a component to display different images. However, after passing the array to the component, the items accessed from the array are showing as undefined, pr ...

transferring data between react components

I am currently working on breaking down code into smaller components, starting with the snippet below from Rows.jsx. I am struggling to grasp how props are passed between parent and child components. Despite reading several guides and articles, I remain un ...

What is the best method to include spacing between strings in an array and then combine them into a csv-friendly format?

The method I am currently employing involves the following: var authorsNameList = authors.map(x => x.FirstName + ' ' + x.LastName); Yet, this generates an outcome similar to this: Bob Smith,Bill Jones,Nancy Smith Nevertheless, the desired ...

In Vue.js, the properties of components are not defined

Currently, I am experiencing an issue where I am passing a props to one of my views, but when I print the result in console it shows up as undefined. This is causing difficulties as I am unable to make requests or consults. Here is the code snippet in ques ...

"Enhance your website with a backspace button using jquery - here's

Recently, I delved into the world of jQuery and decided to test my skills by creating a jQuery calculator. Everything worked perfectly except for the backspace button. This is what I tried: if (value === backspace) { $(input).val($(input).val().substring ...

Is there a way to smoothly transition a FlatList while the keyboard is open?

At the moment, the appearance and animation of my messaging screen are as follows: However, I'm eager to enhance my messaging initial animation to lift up my flatlist like this (opens with scrolling): This is the code for the screen: // Code goes he ...

Image displaying recreation of drop down lists similar to those found on Facebook pop-up windows

Seeking guidance on how to create popup drop-down lists similar to Facebook's "Who liked this link?" feature. I believe it involves the use of jQuery. Click here for an example image. Any suggestions, folks? ...

How do I retrieve the host name of a webpage in server-side rendering using Nuxt.js?

Within my Nuxt.js project, I have a configuration variable for the API environment structured as follows: [ { front_host: local-1.domain.com, backend_api: api-1.domain.com }, { front_host: local-2.domain.com, backend_api: api-2.domain.com }, ] I ...

Utilizing Three.js with interactive functionalities and advanced transformation controls

I'm facing an issue with my project where I am using three.interaction to capture click events on certain objects and add transformControls to them. The problem I'm encountering is that the transform controls seem to block the click event on oth ...

Sending data through AJAX

I am currently working on a calendar project. I want to include a description box next to the calendar, where additional information about an event will be displayed when a user clicks on a specific date. Here is what I have so far in terms of HTML/PHP: ...

How do I correctly submit a Vue.js application to GitHub?

After attempting to upload my files to Github, I received an error message stating that the files were too large. As a workaround, I uploaded only the content of the dist folder after building for production. Although this method worked, it is not very p ...

The toLowerCase method seems to be malfunctioning along with several other functions

JS var score = 0 var yes = "yes" var pokemonName = []; var bg = []; var index = 0; document.getElementById('repete').style.visibility = 'hidden'; (function asyncLoop() { background = bg[num = Math.floor(Math.random() ...

Component triggering a dirty state in Vue

On my Vue page, I have input fields and would like to display a message when any of these input fields are changed. In Angular, this can be done easily with the isDirty function, but in Vue, this functionality is not available. Is there a method to captur ...

Exploring Angular 10's advanced forms: delving into three levels of nested form groups combined with

Project Link: Click here to view the project In my testForm, I have 3 levels of formGroup, with the last formGroup being an array of formGroups. I am trying to enable the price field when a checkbox is clicked. I am unsure how to access the price contro ...

What could be the issue with my interactive dropdown menu?

I am currently experiencing an issue with a drop down list that is supposed to fetch records from a column in another table, but no records are appearing. Additionally, I would like to add an option in the drop down list labeled "others" for users to inp ...