0

What i want to do is also check the default option when a user checks one of the checkbox item.

i have created a snippet of the error i am encountering, usually i thought its because of my nested components.

but i encountered the error You may have an infinite update loop in watcher with expression "localChecked"

even on this simple code snippet.

vue js script

new Vue({
  el: "#app",
  data: {
    application: [
            {
        app_name : 'Netflix',
        app_default : 'videoshare_default',
        options : [
          { text : 'Video Stream', value : 'video_streaming'},
          { text : 'Download Video' , value : 'video_download'},
          { text : 'Share Video' , value : 'videoshare_default'}
        ]
      },
            {
        app_name : 'Messenger',
        app_default : 'message',
        options : [
            { text : 'Messaging', value : 'message'},
          { text : 'Voice Calls' , value : 'voice_calls'},
          { text : 'Video Calls' , value : 'video_calls'},
          { text : 'Media Sharing' , value : 'file_transfer'}
        ]
      }      
    ],
    selected : []
  },
  methods: {
    selectDefault: function(data,$event){
        this.selected[data.app_name].push(data.videoshare_default)
    }
  }
})

HTML

<div id="app">
  <b-col v-for="(data , index) in application" v-bind:key="index" class="p-2" cols="5">
    <b-form-group :label="data.app_name" label-class="font-weight-bold">
      <b-form-checkbox-group                            
         @input="selectDefault(data,$event)"
         v-model="selected[data.app_name]"
         :options="data.options"
         name="application[]"
         stacked
      ></b-form-checkbox-group>
    </b-form-group>
  </b-col>
</div>

a FIDDLE:

https://jsfiddle.net/tomexsans/194m0jdq/1/

or is there any other way to do this than what i am doing.

Community
  • 1
  • 1
tomexsans
  • 4,454
  • 4
  • 33
  • 49
  • Is it something like this (https://jsfiddle.net/6kvew3zf/1/), that you want? – Hiws Apr 30 '20 at 07:41
  • @Hiws this is what i wanted. Yes you should add this as an answer so i can accept. thank you for adding comments in your code as well. – tomexsans Apr 30 '20 at 23:38

1 Answers1

1

Your selected property is an array, but you want to use key value pairs, which is why you need to make it an object instead, which will store an array of each application type.

To make sure that Vue stays reactive, you need to use the Vue.set or this.$set method to add a property to an object, if that property DOESN'T already exist in that object.

The $event on b-form-checkbox-group returns the entire array of selected values, which we don't want. That's why i use the .native modifier on the event, so i can access the clicked checkbox and it's value.

new Vue({
  el: "#app",
  data: {
    application: [{
        app_name: 'Netflix',
        app_default: 'videoshare_default',
        options: [{
            text: 'Video Stream',
            value: 'video_streaming'
          },
          {
            text: 'Download Video',
            value: 'video_download'
          },
          {
            text: 'Share Video',
            value: 'videoshare_default'
          }
        ]
      },
      {
        app_name: 'Messenger',
        app_default: 'message',
        options: [{
            text: 'Messaging',
            value: 'message'
          },
          {
            text: 'Voice Calls',
            value: 'voice_calls'
          },
          {
            text: 'Video Calls',
            value: 'video_calls'
          },
          {
            text: 'Media Sharing',
            value: 'file_transfer'
          }
        ]
      }
    ],
    selected: {}
  },
  methods: {
    selectDefault(data, event) {
      /*  Return if the checkbox was unchecked */
      if (!event.target.checked) return;
      /* Return if the selected value was the default */
      if (data.app_default === event.target.value) return;

      /* Init the array if it doesn't exist yet.*/
      if (!this.selected[data.app_name]) {
        this.$set(this.selected, data.app_name, []);
      }

      const nestedSelected = this.selected[data.app_name];
      /* Push in the default value if it doesn't exist alreayd */
      if (!nestedSelected.find(value => value === data.app_default)) {
        this.selected[data.app_name].push(data.app_default)
      }
    }
  }
})
<link href="https://unpkg.com/bootstrap@4.4.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/bootstrap-vue@2.3.0/dist/bootstrap-vue.css" rel="stylesheet"/>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.3.0/dist/bootstrap-vue.js"></script>

<div id="app">
  <b-col v-for="(data , index) in application" v-bind:key="index" class="p-2" cols="5">
    <b-form-group :label="data.app_name" label-class="font-weight-bold">
      <b-form-checkbox-group
         v-model="selected[data.app_name]"
         @input.native="selectDefault(data, $event)"
         :options="data.options"
         name="application[]"
         stacked
       ></b-form-checkbox-group>
    </b-form-group>
  </b-col>
  
  {{ selected }}
</div>
Hiws
  • 8,230
  • 1
  • 19
  • 36