Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check / Uncheck a Checkbox in a child component with vuejs

Context :

I am using VueJS in a project for the first time so I'm potentially not using it the right way.

I have a parent and a child component :

Parent : ResearchProducts.vue : Displays a list of products that can be filtred by their categories. The filters are checkboxes related to the category of the products.

Child : CategoryDisplay.vue : This is the component that handle the view and the methods of a category row.

My Question :

When I click on a category checkbox inside of my child component and if the checkbox is checked, the category is added to a list of filters in the parent. This works.

When I uncheck the checkbox, the category is removed from this list. This works too.

Now I've showed all my categories as buttons in the parent component to make the filters visible more easily for the user. And my problem is that I want this button to uncheck the related checkbox inside the child component when I click on it.

Here is my actual code :

ResearchProducts.vue :

<template>
 <div>
     <template v-for="category in categories">
          <category-display
                 :category="category"
                 :key="'category_'+category.id"
                 :checked="checked"
                 @categorySelected="categorySelected"
               ></category-display>
     </template>
     <button
               v-for="filter in listFilters"
               :key="'filter_'+filter.slug"
               class="btn btn-light btn-sm mr-2 mb-2"
               @click="removeFilter(filter)"
             >
               {{ filter.name }}
      </button>
 </div>
</template>
<script>
export default {

  data() {

    return {

      categories: { // HERE A COLLECTION CONTAINING ALL MY CATEGORIES },

      selectedCategories: [],

      listFilters: []

    };

  },

  methods: {

    categorySelected(category) {

      var newCategory = {

        type: "category",

        slug: category.slug,

        name: category.name

      };

      if (category.checked) {

        if (!this.selectedCategories.includes(category.slug)) {

          this.selectedCategories.push(category.slug);

          this.listFilters.push(newCategory);

        }

      } else {

        if (this.selectedCategories.includes(category.slug)) {

          const index = this.selectedCategories.indexOf(category.slug);

          if (index > -1) {

            this.selectedCategories.splice(index, 1);

          }

        }

        this.listFilters = this.listFilters.filter(function(item) {

          for (var key in newCategory) {

            if (item[key] === undefined || item[key] == newCategory[key])

              return false;

          }

          return true;

        });

      }

    },

    removeFilter(filter) {
     // THERE, I NEED TO UNCHECK THE RELATED CHECKBOX IN CHILD COMPONENT
     this.listFilters = this.listFilters.filter(function(item) {
        for (var key in filter) {
          if (item[key] === undefined || item[key] == filter[key]) return false;
        }
        return true;
      });

    }

  }

};
</script>

CategoryDisplay.vue :

<template>
  <b-form-checkbox-group class="w-100">
    <b-form-checkbox :value="category.slug" class="w-100" @input="selection" v-model="selected" ref="checked">
      {{ category.name }}
      <span class="badge badge-secondary float-right">{{ category.products_count }}</span>
    </b-form-checkbox>
  </b-form-checkbox-group>
</template>

<script>
export default {
  props: {
    category: {
      type: Object,
      required: true
    }
  },

  data() {
    return {
      selected: false
    }
  },

  methods: {
    selection() {
      var response = false;
      if(this.selected.length !== 0){
        response = true;
      }
      this.$emit('categorySelected', {slug: this.category.slug, name: this.category.name, checked: response});
    }
  }
};
</script>
like image 488
mickael Avatar asked Jun 17 '20 12:06

mickael


People also ask

How do you check checkbox is checked or not in Vuejs?

To watch for checkbox clicks in Vue. js, we can listen to the change event. to add the @change directive to the checkbox input to listen to the change event. Then we can get the checked value of the checkbox with e.

How do I check a checkbox in Vue?

Vue Set Checkbox as Checked To do this, we need to bind the checkbox value with the v-model directive. This can be done by applying simple logic, and that is. Set the checkbox value to true, so if the value is truthy, then the initial state will be checked.

How do I pass Click event from parent to child in Vue?

To pass an event from parent to child, we can pass a Vue instance to the child, emit events from the parent, and listen to it with the Vue instance we passed into the child.

How do you call parent method from child component in Vue?

To call parent method with component with Vue. js, we can get the parent component's method from the $parent property. to define the child component with Vue. component .


1 Answers

Here is a simplified sample for your reference. You can use the sync modifier to achieve a two-way-binding between the parent and child. That together with a computed property in the child with a setter and getter

So passing all categories to child, and sync the selected categories:

<HelloWorld :cats.sync="selectedCategories" :categories="categories"/>

Child component takes the categories, iterates and shows checkboxes. Here we use the computed property, and when a checkbox is clicked, the setter emits the change to the parent:

<label v-for="c in categories" :key="c.id">
  <input v-model="temp" type="checkbox" :value="c">
  {{ c.name }}
</label>

script:

computed: {
  temp: {
    get: function() {
      return this.cats;
    },
    set: function(newValue) {
      this.$emit("update:cats", newValue);
    }
  }
}

And the parent just simply iterates the selectedCategories and as you wish, when a change happens in parent for selectedCategories, child will be automatically aware of when an item is deleted.

Here's a full sample for your reference: SANDBOX

like image 95
AT82 Avatar answered Oct 22 '22 19:10

AT82