What are strategies for handling intricate state logic within my Vue.js checkbox component?

I'm facing a few challenges as I dive into learning Vue.js for just one week. Keep in mind that this example is actually nested within a parent component called <question>, but for the sake of simplicity, I've streamlined the code for this post.

  1. Is there a way to have certain items pre-checked when the page loads?

Edit — I cracked number 1. Just needed to use

[ "Chicken", "Turkey", "Beef", "Fish", "Pork" ]

  1. How can I deselect specific items, like unchecking meat options if I choose Vegan?
  2. How do I add Exclude and Include checkboxes next to my options?

https://i.stack.imgur.com/GGOSe.gif

Checkbox

<div id="questionnaire">
  <checkbox v-model="form.meats" id="8a"  option="Chicken"></checkbox>
  <checkbox v-model="form.meats" id="8b" option="Turkey"></checkbox>
  <checkbox v-model="form.meats" id="8c" option="Beef"></checkbox>
  <checkbox v-model="form.meats" id="8d" option="Pork"></checkbox>
  <checkbox v-model="form.meats" id="8e" option="Fish"></checkbox>
  <checkbox v-model="form.meats" id="8f" option="Vegetarian Only"></checkbox>
  <checkbox v-model="form.meats" id="8g" option="Vegan Only"></checkbox>
  {{ form.meats }}
</div>

Vue.component('checkbox')

Vue.component('checkbox', {
  template: `
    <div>
            <input type="checkbox" :id="id" :value="option" v-model="checked" @change="update">
            <label :for="id">
                {{ option }}
                <slot></slot>
            </label>
    </div>
    `,
  data() {
    return {
      checkedProxy: false
    }
  },
  computed: {
    checked: {
      get() {
        return this.value
      },
      set(option) {
        this.checkedProxy = option
      }
    }
  },
  methods: {
    update: function(e) {
      this.$emit('input', this.checkedProxy)
    }
  },
  props: {
    value: null,
    option: null,
    id: {
      type: String,
      required: true
    }
  }
});

new Vue({
  el: "#questionnaire",
  data: {

    form: {

      meats: [],

    }
  }
})

Answer №1

I believe these are the details you're looking for.

<div id="questionnaire">
  <check-group :chks="chks" v-model="form.meats"></check-group>
  {{ form.meats }}
</div>

const elements = {
    '1': {
        tag: 'meats',
        exclusiveGroups: [2]
    },
    '2': {
        tag: 'vegan',
        exclusiveGroups: [1,3]
    },
    '3': {
        tag: 'Vegetarian Only',
        exclusiveGroups: [1,2]
    }
}

const checkboxes = {
    'Chicken': {
        groupIds: [1]
    },
    'Turkey': {
        groupIds: [1]
    },
    'Beef': {
        groupIds: [1]
    },
    'Pork': {
        groupIds: [1]
    },
    'Fish': {
        groupIds: [1]
    },
    'Vegetarian Only': {
        groupIds: [3]
    },
    'Vegan Only': {
        groupIds: [2]
    }
}

Vue.component('checkbox', {
    template: `
    <div>
        <label>
            <input type="checkbox" ref="chk" :value="val" v-model="value" @change="update($event)">
            {{ txt }}
            <slot></slot>
        </label>
        <input type="checkbox" :checked="value.indexOf(val)<0" @change="reverseSelection($event)">
    </div>
    `,
    data () {
        return {
            val: this.optValue || this.optText,
            txt: this.optText || this.optValue
        }
    },
    methods: {
        update (e) {
            this.$emit('input', this.value, e.target.value, e.target.checked)
        },
        reverseSelection () {
            var e = document.createEvent("MouseEvents");
            e.initEvent("click", true, true);
            this.$refs.chk.dispatchEvent(e);
        }
    },
    props: ['value','optValue','optText']
});

Vue.component('check-group',{
    template: `
        <div>
            <checkbox v-for="item in chks" :opt-value="item.value" :opt-text="item.text" @input="update" v-model="value"></checkbox>
        </div>
    `,
    props: {
        value: {
            required: true,
            type: Array
        },
        chks: {
            required: true,
            type: Array
        }
    },
    methods: {
        update (val,curVal,checked) {
            if(checked){
                chks[curVal].groupIds.forEach(id=>{
                    groups[id].exclusiveGroups.forEach(eid=>{
                        for(let i=0;i<val.length;i++){
                            let p = chks[val[i]].groupIds.indexOf(eid)
                            if(p>=0){
                                val.splice(p,1)
                                i--
                            }
                        }
                    })
                })
            }
            this.$emit('input',val)
        },
    }
})

new Vue({
    el: "#questionnaire",
    data: {
        chks: Object.keys(chks).map(key=>({value: key,groupIds: chks[key]})),
        form: {
            meats: ['Chicken']
        }
    }
})

If you want to ensure that vegan and vegetarian options cannot be selected simultaneously, make the following adjustments to the definitions of groups and checkboxes:

const elements = {
    '1': {
        tag: 'meats',
        exclusiveGroups: [2]
    },
    '2': {
        tag: 'vegan',
        exclusiveGroups: [1,3]
    },
    '3': {
        tag: 'Vegetarian Only',
        exclusiveGroups: [1,2]
    }
}

const checkboxes = {
    'Chicken': {
        groupIds: [1]
    },
    'Turkey': {
        groupIds: [1]
    },
    'Beef': {
        groupIds: [1]
    },
    'Pork': {
        groupIds: [1]
    },
    'Fish': {
        groupIds: [1]
    },
    'Vegetarian Only': {
        groupIds: [3]
    },
    'Vegan Only': {
        groupIds: [2]
    }
}

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

AJAX - Self-Executing Anonymous Function

I have a question that may seem trivial, but I want to make sure I'm heading in the right direction. I've created two different versions of an XMLHttpRequest wrapper, and both are functioning correctly. const httpRequest = function () { let ...

The issue with the ng-click property not triggering arises when it is assigned to a button that is generated dynamically

I need to construct a table dynamically based on the results returned from SQL. In this scenario, populating the table with the start time, end time, and user is straightforward: var StartTime = document.createElement('td'); var EndTime = docume ...

Dynamic value updates using jQuery input type formulas

I need help with a form that has two inputs: The first input allows the user to enter an amount, such as 1000. The second input is read-only and should display the value of the first input plus 1%. For example, if the user types in 1000 in the first fie ...

Dealing with intricate query parameters in Express.Js

Currently, I am working on developing REST APIs using Express.js. One particular express route that I have set up is as follows: /api/customer I have incorporated multiple query parameters into this route, such as: /api/customer?name=jake /api/customer?c ...

Suggestions for updating the 'begin' and 'finish' variables transmitted through ajax on fullcalendar?

Shown below is the URL to request JSON data via Ajax: '/php/get-events.php?start=2015-05-31&end=2015-06-07&_=1433154089490'. This query will fetch JSON data from 2015-05-31 to 2015-06-07. However, I am looking to retrieve data over a ...

The supported browser is unable to import ES6 modules

Attempting to incorporate moment.js as an es6 module. The most recent version of Chrome is being utilized. Referring to the conversation here, I experimented with the src path (es6) import * as moment from './node_modules/moment/src/moment' A ...

The package 'models' imported from is not found [ERR_MODULE_NOT_FOUND] error

I'm currently in the process of setting up my project to utilize absolute imports. To accomplish this, I've made adjustments to my jsconfig.json file as shown below: { "compilerOptions": { "baseUrl": "./src&quo ...

What is the best way to send the accurate data type from PHP to Javascript?

My approach involves using the jQuery post method to insert a record in MySQL. The issue I'm facing is that when comparing the output of the PHP using ==, all three conditionals function correctly. However, with ===, the first two conditionals return ...

Using the jquery slider in conjunction with the onchange event

I have integrated a jquery slider add-on into my project that updates a value in a Linux file whenever it is manipulated. The slider is connected to a text input box, which is set as readonly and therefore always blurred. The issue I am facing is that the ...

"Interested in capturing an event.target using Vue? Here's how you can catch an eme

Looking for assistance on catching an emitted event target using Vue. I am attempting to create an $emit Vue but encountering an error. I have tried to capture an event target emit from a child component coming from an input, passing the onChange input st ...

The hidden DIV containing an ASP.NET CheckBox consistently yields a value of false

I have a group of form elements located within a hidden div which looks like this: <div id="jDivUpdateFolder" style="display:none;"> <asp:TextBox ID="txtEditFolderName" runat="server"></asp:TextBox><br /> <asp:TextBox ID ...

Guide to uploading multiple images to an Amazon AWS S3 bucket using Node.js, Angular, and JavaScript

Can anyone share insights on where and how E-commerce websites typically upload their product images? Has anyone had experience using Amazon AWS S3 bucket for this purpose? Additionally, does anyone know how to upload or retrieve multiple images at once ...

The type 'void | Observable<User>' does not include the property 'subscribe'. Error code: ts(2339)

authenticate() { this.auth.authenticate(this.username, this.password).subscribe((_: any) => { this.router.navigateByUrl('dashboard', {replaceUrl: true}); }); } I'm puzzled by this error message, I've tried a few solu ...

Struggling to see the Vuetify 'v-select' component on the screen

Welcome to my personal website <template> <v-form> <v-select outlined label="Select a segment from the AI/ML model" :items="options"> </v-select> <v-text-field label="Enter User ID" required>&l ...

Utilizing Locale to Rewrite URLs in Next.js Version 13

I've been attempting to rewrite the URL based on the locale extracted from my middleware.js, but for some reason, the URL isn't being rewritten and leads to a page-not-found error 404. Strangely though, if I manually navigate to "localhost:3000/e ...

Update WooCommerce Mini-cart with ajax refresh

I'm having an issue with my custom plugin where everything is working properly, except for the fact that the mini cart is not updating after adding items. I have tried various methods to trigger a refresh, but so far nothing has worked. Below is a sni ...

What is the better choice in NodeJS: using "return cb(..)" or first calling cb(..) and then returning?

Forgive me if this sounds like a silly question, but I'm curious about the implications of something: Whenever I encounter an error or need to complete a function flow, I follow certain instructions such as: if(err) { cb(err); // or for exampl ...

Ways to modify the default text in a dropdown menu?

I'm currently attempting to modify the title of a dropdown using the Multi-select plugin found here. However, I've encountered an issue where I am unable to dynamically change the text (Dropdown title) of the dropdown using JavaScript. $(' ...

How can I change the padding that is being inherited from "@ .MuiAlert-icon"?

Is there a method to override the padding inherited from "@ .MuiAlert-icon"? The Chrome inspector indicates that the current padding is set to 7px. .MuiAlert-icon { display: flex; opacity: 0.9; padding: 7px 0; font-size: 22px; ...

Installing v8-profiler on Windows 8 (64 bit) through npm: a step-by-step guide

The v8-profiler module is widely recognized as the go-to tool for identifying memory leaks in node.js applications. However, attempting to install it with npm install v8-profiler results in an error message related to compatibility issues between 32bit an ...