Managing multiple checkboxes in a Vue component

I have a checkbox component in Vue:

<template>
    <div class="checkbox">
        <input class="checkbox-input" name="input" type="checkbox" v-model="checkbox">
    </div>
</template>
  
<script>
export default {
    data(){
        return {
            checkbox: false
        };
    },
};
</script>

So in the parent component I want to control these checkbox. So here is my parent component:

<div class="card">
    <div class="card-header">
        <CheckBox />
    </div>
<div class="card-body" v-for="item in cart" :key="item.product.id">
    <div class="checkbox-area">
        <CheckBox />
    </div>
</div>

So checkbox in card-body can be added when user clicks to add. So if a user clicks 3 times, 3 checkbox are being added inside of card-body. What I am trying to achieve is, as you see in card-header there is another checkbox, and when this checkbox is clicked, I want to check all the checkboxes inside card-body, and when it is unchecked in card-header, I want to unchcecked everything inside card-body.

So do you have any idea how to achieve this?

Thanks...

Answer №1

If you want to implement a checkbox functionality like this:

Vue.component('checkbox', {
  template: `
    <div class="checkbox">
        <input class="checkbox-input" name="input" type="checkbox" @change="getCheck" v-model="value">
    </div>
  `,
  props: {
    checked: {
      type: Boolean,
      default: false
    }
  },
  data(){
    return {
      value: this.checked
    };
  },
  methods: {
    getCheck() {
      this.$emit("set-checked", this.value)
    }
  },
  watch: {
    checked(){
      this.value = this.checked
    }
  }
})

new Vue({
  el: '#demo',
  data(){
    return {
      all: false,
      cart: [
        {id: 1, check: false},
        {id: 2, check: false},
        {id: 3, check: true},
        {id: 4, check: false}
      ]
    };
  },
  watch: {
    cart() {
      this.cart.find(c => c.check === false) ? this.all = false : this.all = true
    }
  },
  methods: {
    checkAll(val) {
      this.all = val
      this.cart = this.cart.map(c => {
        c.check = val 
        return c
      })
    },
    checkItem(id) {
      this.cart = this.cart.map(c => {
        if(c.id === id) {
          c.check = !c.check 
        }
        return c
      })
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <div class="card">
    <div class="card-header">
    <p>All</p>
      <checkbox :checked="all" @set-checked="checkAll" />
    </div>
    <br/>
    <div class="card-body" v-for="item in cart" :key="item.id">
      <div class="checkbox-area">
        <checkbox :checked="item.check" @set-checked="checkItem(item.id)" />
      </div>
    </div>
  </div>
</div>

Answer №2

To begin, ensure that you include necessary props in your Component and set up a watcher to trigger a sync event when the checkbox value changes.

<template>
    <div class="checkbox">
        <input class="checkbox-input" name="input" type="checkbox" v-model="value">
    </div>
</template>

<script>
export default {
    props: {
        checked: {
            type: Boolean,
            default: false
        }
    }
    data(){
        return {
            value: this.checked
        };
    },
    watch: {
        value(){
            this.$emit("update:checked", this.value)
        }
    }
};
</script>

Next, implement functionality on the cart to monitor these changes and enable checking/unchecking of all items accordingly.

<template>
    <div class="card">
        <div class="card-header">
            <CheckBox :checked.sync="global"/>
        </div>
        <div class="card-body" v-for="item in cart" :key="item.product.id">
            <div class="checkbox-area">
                <CheckBox :checked.sync="item"/>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return {
            global: false,
            cart: [
                false,
                false,
                false
            ]
        };
    },
    watch: {
        global(){
            for (let i = 0; i < this.cart.length; i++) {
                this.chart[i] = this.global
            }
        }
    }
};
</script>

This code has not been tested, but it should function as expected...

Answer №3

Utilizing checkbox input as custom components can present some challenges, but the following code snippet may assist you:

code sandbox

  Vue.component('checkbox', {
    template: `
    <label>
        <input type="checkbox" :value="value" v-model="deltaValue" />
        {{ label }}
    </label>
    `,
    name: "checkbox",
    model: {
       prop: 'modelValue',
       event: 'update:modelValue'
    },
    props: {
      label: String,
      value: [Object, Boolean, Array],
      modelValue: {
        type: [Array, Boolean],
        default: () => [],
      },
    },
    computed: {
      deltaValue: {
        get() {
          return this.modelValue;
        },
        set(value) {
          this.$emit("update:modelValue", value);
        },
      },
    },
  });
  
  new Vue({
    el: '#app',
    data() {
        return {
          areAllSelected: false,
          checkedItems: [],
          cart: [
            { id: 1, name: "tablet"},
            { id: 2, name: "phone"},
            { id: 3, name: "PC" },
          ],
        };
      },
      watch: {
        areAllSelected(areAllSelected) {
          if (areAllSelected) {
            this.checkedItems = [...this.cart];
            return;
          }
          this.checkedItems = [];
        },
        checkedItems(items){
          if (items.length === this.cart.length) {
            this.areAllSelected = true;
            return;
          }
    
          if (items.length === 0) {
            this.areAllSelected = false;
          }
        }
      },
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div class="card">
    {{ checkedItems }}
    <div class="card-header">
      <checkbox label="check all" v-model="areAllSelected" />
    </div>
    <hr />
    <div class="card-body" v-for="product in cart" :key="product.id">
      <checkbox
        :label="product.name"
        :value="product"
        v-model="checkedItems"
      />
    </div>
  </div>
</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 function Page.render() will output a value of false

Currently, I am utilizing phantomjs to capture screenshots of multiple webpages. The code snippet below is what I have used to generate a screenshot image. var page = require('webpage').create(); page.viewportSize = { width: 1200,height: 800}; ...

Map does not provide zero padding for strings, whereas forEach does

Currently working on developing crypto tools, I encountered an issue while attempting to utilize the map function to reduce characters into a string. Strangely enough, one function works perfectly fine, while the other fails to 0 pad the string. What could ...

The div layer is positioned above the flash object

I have successfully implemented a method where I position a div over a webpage containing a flash object. This absolutely positioned div has a high z-index and captures click events. The main goal is to trigger the click event on the div when the flash obj ...

Replicating row with distinct values

I'm experiencing some difficulties with a particular issue. I currently have two tables as shown below: <table id="customFields1" class="table table-bordered table-hover additionalMargin alignment"> <thead> <tr> < ...

Encountering a problem with AngularJS - receiving the [ng:areq] error, for more information visit http://errors.angularjs.org/1.3.2/ng/areq

While working on my CRUD angularApp, I encountered a strange error in Chrome dev tools. Here is the complete error message: error: [ng:areq] http://errors.angularjs.org/1.3.2/ng/areq?p0=DbController&p1=not%20a%20function%2C%20got%20string at angular.j ...

Having difficulty implementing two-way binding on SELECT element within Angular JS programmatically

Struggling with implementing two-way binding for SELECT elements. Attempting to dynamically change the selected element through code. While I've come across examples on Stackoverflow for binding the change event for SELECT, finding resources on the ap ...

Steps for Disabling Autocomplete in a JSP Page

How can I prevent the browser from remembering the username and password on my JSP page after submitting the form? I've already tried using autocomplete=off in the JSP code. <form name="indexFrm" id="indexFrm" autocomplete="off" method="post"> ...

Determining the state update value in useEffect using dispatch and payload in Redux

Apologies for the confusion in the title. I am currently working with React and Redux-toolkit. I encountered an issue where when referencing the updated value in the useState set function, I ended up getting the value before the update. I understand that ...

Swapping out the entire vue.js container

I have a custom vue.js widget that I initialize like so: var myWidget = new Vue({ el: '#widget-container', methods: { loadData:function() { // custom functionality here } }, }); The HTML structure is as f ...

Issue with grunt-crx task detected

In my Gruntfile, I've integrated the grunt-crx task as shown below: crx: { packExtension: { src: "../build/unpacked", dest: "../build/dist" } } Whenever I execute the crx task on its ow ...

The expression in the v-if directive encountered an error during evaluation

I am struggling to find a way to check for a value in my Vue component. Here is the code I have: var userContent = Vue.extend({ template: ` <div class="LayersMenuSectionContent" v-if="userContent.rasters_previews_list.data.length > 0"&g ...

Encountering an issue with Angular routing: Cross-origin requests are restricted to specific protocol schemes, such as HTTP

I encountered an error while working on angular routing. Below is my HTML code snippet: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <script src= ...

Tips for styling buttons in react-admin with custom CSS

I need some help with customizing buttons in react-admin. I am new to the platform and unsure about how to go about changing the button CSS for various actions such as create, edit, and export. Can anyone provide guidance on the best way to customize these ...

Activate a specific component of hover effect within multiple components generated by the `v-for` loop

Hey there! I'm currently facing a CSS challenge related to Vue. Let's say I want to display multiple components using v-for, and I want to add a hover effect to each component individually. The goal is to have the hover effect only apply to the c ...

What is the method to deactivate multiple links using jQuery?

Below is the HTML code: <a title="Login" data-href="/MyAccount/Access/Login" data-title="Admin" data-entity="n/a" id="loginLink" class="nav-button dialogLink"><b>Login</b></a> <a title="Register" data-href="/MyAccou ...

IDEA 2021.2 NPM SCRIPTS: Looks like there are no scripts available

Searching through the npm scripts, I am unable to locate any, however package.json does contain: ...

The div structure generated through JavaScript appears distinct from its representation in the live DOM

Currently, I am facing a challenge with creating a complex nested Div structure within a JavaScript loop that iterates over JSON response objects from the Instagram API. The main goal is to set the URL for each image within a specific Bootstrap div layout. ...

How to properly log out a user in Vue.js?

Hey there, Currently, I am working with the combination of Laravel and VueJS, but I seem to be facing an issue regarding disconnection. For instance: If I log out from one tab and then switch to another tab, I find that I am still able to carry out actio ...

Search through array elements that are nested deeply

Consider the following scenario: an array is provided as input containing various objects with nested elements. The goal is to filter this array in JavaScript and obtain a new array consisting only of objects where the key "navigation" has a value of true. ...

Tips for halting click propagation in VueJS

My dilemma lies within a recursive list (tree) where each element contains a @click="sayHello(el.id)". The challenge arises due to the nested structure of the list, such as: list-element-0-01 ├──list-el-1-01 │ └──list-el-2-01 └──list ...