0

I have a vue page that loads a bunch of actions from a database. It then creates a table with some data got from the action, using v-for.

Here is my problem: In one of the table rows I need a checkbox that is v-modeled to an attribute, action.weekly. Ideally, it will be a boolean. But there are a bunch of action entries in my database that don't have a weekly attribute. In those cases, I need the checkbox checked, as if it were true. Normally, I would use a computed property here, but you can't pass arguments to computed properties, so I don't know how to tell vue which action to look at at (I can't pass $event, ndx in to a computed property like I am doing below with handleEnableChanged() ).

Here is my code for the table:

<tbody>
            <tr v-for="(action, ndx) in actions" >
              <td class="pointer" @click='openModalCard(action, ndx)'>
                {{action.name}}
              </td>
                <input type="checkbox" v-model="action.weekly??" @change="handleEnableChanged($event, ndx)"/>
              </td>
                <input type="checkbox" v-model="action.enabled" @change="handleEnableChanged($event, ndx)">
              </td>
            </tr>
            </tbody>

In the cases where action does not have a weekly attribute, I want the checkbox checked as if it were true. How can I accomplish this?

If there is a better way to approach this, please let me know. I'm still a novice with vue.js.

Brian
  • 385
  • 1
  • 5
  • 23
  • 1
    Can you just `v-if` it? – Steven B. Dec 16 '19 at 18:32
  • 1
    As far as I understand it, v-if is only for optional rendering. I want the checkbox rendered either way, but I want it checked if the v-model attribute is true or undefined. – Brian Dec 16 '19 at 18:39

3 Answers3

1

I think it would be easiest to use v-if and v-else for this.. With that being said, I have also provided an example of how to handle this without v-if and v-else..

Using v-if and v-else:

new Vue({
  el: "#root",
  data: {
    actions: [
        {
          name: "first",
          weekly: true,
          enabled: false
        },
        {
          name: "second",
          enabled: false
        },
        {
          name: "third",
          weekly: true,
          enabled: true
        },
        {
          name: "fourth",
          enabled: true
        }
      ]
  },
  template: `
<tbody>
  <tr v-for="(action, ndx) in actions" >
    <td class="pointer" @click='console.log(action, ndx)'>{{action.name}}</td>
    <input v-if="'weekly' in action" type="checkbox" v-model="action.weekly" @change="handleEnableChanged($event, ndx)"/>
    <input v-else type="checkbox" checked="true" @change="handleEnableChanged($event, ndx)"/>
    </td>
    <input type="checkbox" v-model="action.enabled" @change="handleEnableChanged($event, ndx)">
    </td>
  </tr>
</tbody>
  `,
  methods: {
    handleEnableChanged(evt, ndx) {
      console.log(evt, ndx);
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="root"></div>

Without v-if and v-else:

new Vue({
  el: "#root",
  data: {
    actions: ""
  },
  template: `
<tbody>
  <tr v-for="(action, ndx) in actions" >
    <td class="pointer" @click='console.log(action, ndx)'>{{action.name}}</td>
    <input type="checkbox" v-model="action.weekly" @change="handleEnableChanged($event, ndx)"/>
    </td>
    <input type="checkbox" v-model="action.enabled" @change="handleEnableChanged($event, ndx)">
    </td>
  </tr>
</tbody>
  `,
  methods: {
    handleEnableChanged(evt, ndx) {
      console.log(evt, ndx);
    },
    getActions() {
      let originalActions = [
        {
          name: "first",
          weekly: true,
          enabled: false
        },
        {
          name: "second",
          enabled: false
        },
        {
          name: "third",
          weekly: true,
          enabled: true
        },
        {
          name: "fourth",
          enabled: true
        }
      ];
      this.actions = originalActions.map(a => { 
        return {
          name: a.name,
          weekly: 'weekly' in a ? a.weekly : true,
          enabled: a.enabled
        }
      })
    }
  },
  created() {
    this.getActions();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="root"></div>
Matt Oestreich
  • 8,219
  • 3
  • 16
  • 41
0

If you want all items in the array to have an action.weekly property, then update your data when it is initially retrieved. You can then just use v-model="action.weekly" for all items in the array.

this.newArray = this.oldArray.map(item => {
  if(!item.hasOwnProperty('weekly')){
    item.weekly = true;
  }
  return item
})
paddyfields
  • 1,466
  • 2
  • 15
  • 25
  • 1
    If `item.weekly` is `false`, wouldn't this just change it to `true`? I think a better way to check for the existence of the `weekly` key would be to do something like: `if('weekly' in item){...}` – Matt Oestreich Dec 16 '19 at 19:55
  • 1
    Ah yes, my mistake. Yes you'd need to check it exists first before setting to true. I'll update the answer. – paddyfields Dec 16 '19 at 19:57
0

You can just do this:

<input type="checkbox" :checked="!!action.weekly">

The !! operator will return true if the value is not undefined or empty

AlekseyHoffman
  • 2,438
  • 1
  • 8
  • 31