0

can anyone explain this case?

I currently have a custom checkbox vue component that looks like this (I am using tailwindcss by the way it is so cool)

// MyCheckbox.vue

<template>
  <div class="grid grid-flow-col auto-cols-max gap-1 place-items-center">
    <input
      @change="(event) => $emit('update:checked', event.target.checked)"
      type="checkbox"
      :checked="checked"
      :class="{ 'cursor-pointer': !disabled }"
      class="bg-white my-checkbox appearance-none h-5 w-5 m-1 border text-royal border-grey-2 checked:bg-royal rounded focus:outline-none"
    />
    <label v-if="label" class="font-medium">{{ label }}</label>
  </div>
</template>

<script>
export default {
  name: 'MyCheckbox',
  props: {
    checked: {
      type: Boolean,
      default: false,
    },
    label: {
      type: String,
      default: '',
    },
  },
},
</script>

<style lang="scss" scoped>
.my-checkbox:checked {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0id2hpdGUiPgogIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTE2LjcwNyA1LjI5M2ExIDEgMCAwMTAgMS40MTRsLTggOGExIDEgMCAwMS0xLjQxNCAwbC00LTRhMSAxIDAgMDExLjQxNC0xLjQxNEw4IDEyLjU4Nmw3LjI5My03LjI5M2ExIDEgMCAwMTEuNDE0IDB6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIC8+Cjwvc3ZnPg==);
  border-color: transparent;
  background-size: 100% 100%;
  background-position: 50%;
  background-repeat: no-repeat;
}

If I generate that component with a v-for loop in another component like the code below, the v-model is not changed whenever I check-uncheck it.

// AnotherComponent.vue

<template>
  <div class="grid grid-flow-col auto-cols-max gap-6">
    <my-checkbox
      v-for="obj in [{ state: true, id: 1 }, { state: true, id: 2 }, { state: false, id: 3 }]"
      :key="obj.id"
      v-model:checked="obj.state"
      :label="`Item ${obj.state}`"
    />
  </div>
</template>

<script>
  import MyCheckbox from '@/components/MyCheckbox.vue';

  export default {
    name: 'AnotherComponent',
  }
</script>

But the states change when I loop through a local state like this, it works properly

// AnotherComponent.vue

<template>
  <div class="grid grid-flow-col auto-cols-max gap-6">
    <my-checkbox
      v-for="obj in anArrayOfObj"
      :key="obj.id"
      v-model:checked="obj.state"
      :label="`Item ${obj.state}`"
    />
  </div>
</template>

<script>
  import MyCheckbox from '@/components/MyCheckbox.vue';

  export default {
    name: 'AnotherComponent',
    data() {
    return {
      anArrayOfObj: [
        { state: false, id: 1 },
        { state: false, id: 2 },
        { state: false, id: 3 },
        { state: false, id: 4 },
        { state: true, id: 5 },
      ],
    }
  }
</script>

Is [{ state: true, id: 1 }, { state: true, id: 2 }, { state: false, id: 3 }] can't be reactive? If yes, is there a workaround to manipulate the boolean v-model inside it? Because I'm getting the array from a v-slot scoped slot data in another case (involving another more-complex-component)

lorem_impus
  • 320
  • 3
  • 9
  • Found the answer right here https://stackoverflow.com/questions/57974480/v-model-directives-cannot-update-the-iteration-variable-itself thank you – lorem_impus Mar 31 '21 at 15:45

1 Answers1

0

I think this is correct behaviour. In your first case,everytime v-for gets [{ state: true, id: 1 }, { state: true, id: 2 }, { state: false, id: 3 }]. So, checkbox q & 2 will always have state = true and checkbox 3 will always have state=false. Although you change the value of state from witing the checkbox, again, the props sent to checkbox becomes the same as before since, you are providing the new array everytime with v-for.

But, in second case, since, you are providing reactive data from vue, when you change the value, the state gets updated, and your checkbox works. The array of object provided here is same everytime.

I'm not sure if I was able to answer this the best way, but other people might provide you better explanation.

priosshrsth
  • 1,070
  • 2
  • 11
  • 30