JaChNo
JaChNo

Reputation: 1563

v-if not working inside v-for

I am looping though some data using a v-for and displaying it in a table. I want to conditionally display some text based on one of the values in the array

my html looks like

  <div id="vue-wrapper">
        <div class="table table-borderless" id="table">
            <table class="table table-borderless" id="table">
                <thead>
                <tr>
                    <th>Name</th>
                    <th>Status</th>
                    <th>Actions</th>
                </tr>
                </thead>
                <tr :key=item v-for="item in items">
                    <td>@{{ item.module }}</td>
                    <td>@{{ item.enabled }}</td>
                    <div v-if="item.enabled == true">
                        <td>Disable Button </td>
                    </div>
                    <div v-else>
                        <td>Enable Button </td>
                    </div>
                </tr>
            </table>
        </div>
    </div>

and my vue js looks like

const app = new Vue({
            el: '#vue-wrapper',
            data: {
                items: [{"module":"Blog","enabled":false},{"module":"Booking","enabled":true},{"module":"Review","enabled":true}],
                hasError: true,
                hasDeleted: true,
                newItem: {'name': ''}
            },
            created () {
            //  this.getVueItems()
            },
            methods: {
                getVueItems: function () {
                    axios.get('/api/module/').then(response => {
                        console.log(response.data)
                        this.items = response.data;
                        console.log(this.items);
                    });
                },
                createItem: function () {
                },
                deleteItem: function () {
                },
            }
        });

But when I load the page, both the disabled button and enabled button text is displayed. and there is the following error

"TypeError: Cannot read property 'enabled' of undefined"

but i can read the enabled property in the for loop, so I am not sure what i need to change

Upvotes: 0

Views: 872

Answers (2)

Daniel Beck
Daniel Beck

Reputation: 21475

<div> elements can't be a direct child of a <tr>, so those are getting bumped outside the v-if loop.

In this case you could put the v-if directly on the td, but in cases where that isn't an option, you can use <template> tags instead of a real HTML node:

const app = new Vue({
  el: '#vue-wrapper',
  data: {
    items: [{
      "module": "Blog",
      "enabled": false
    }, {
      "module": "Booking",
      "enabled": true
    }, {
      "module": "Review",
      "enabled": true
    }],
    hasError: true,
    hasDeleted: true,
    newItem: {
      'name': ''
    }
  },
  created() {
    //  this.getVueItems()
  },
  methods: {
    getVueItems: function() {
      axios.get('/api/module/').then(response => {
        console.log(response.data)
        this.items = response.data;
        console.log(this.items);
      });
    },
    createItem: function() {},
    deleteItem: function() {},
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="vue-wrapper">
  <div class="table table-borderless" id="table">
    <table class="table table-borderless" id="table">
      <thead>
        <tr>
          <th>Name</th>
          <th>Status</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tr  v-for="item in items">
        <td>@{{ item.module }}</td>
        <td>@{{ item.enabled }}</td>
        <template v-if="item.enabled == true">
          <td>Disable Button </td>
        </template>
        <template v-else>
          <td>Enable Button </td>
        </template>
      </tr>
    </table>
  </div>
</div>

Upvotes: 0

Daniel
Daniel

Reputation: 35684

I think this is an issue with the use of your td/tr/div tags

            <tr :key=item v-for="item in items">
                <td>@{{ item.module }}</td>
                <td>@{{ item.enabled }}</td>
                <div v-if="item.enabled == true">
                    <td>Disable Button </td>
                </div>
                <div v-else>
                    <td>Enable Button </td>
                </div>
            </tr>

The div actually falls outside of the the tr, and is not necessary anyway, as you can put logic into the td Try using this instead:

            <tr :key=item v-for="item in items">
                <td>@{{ item.module }}</td>
                <td>@{{ item.enabled }}</td>
                <td v-if="item.enabled == true">Disable Button</td>
                <td v-else>Enable Button</td>
            </tr>

Upvotes: 1

Related Questions