2

How can I conditionally enable/disable @click with v-if/v-else while iterating through with v-for on a <th>?

I have the following code:

<template>
  <div id="TableHeaderDiv" class="TableHeaderClass">
    <table cellpadding="0" cellspacing="0" border="0">
      <thead>
        <tr>
          <th
            v-for="column in columns"
            v-bind:key="column.DataField"
            @click="sortBy(column.DataField)"
            :class="{ active: sortKey == column.DataField }"
            :style="{ width: column.Width }"
          >
            {{ column.DisplayText }}
            <div v-if="!column.isControl">
              <span
                class="arrow"
                :class="sortOrders[column.DataField] > 0 ? 'asc' : 'dsc'"
              ></span>
            </div>
          </th>
        </tr>
      </thead>
    </table>
  </div>
</template>

I would like to write a condition so that v-if="!column.isControl" ... add the @click to the <th>.

My initial approach was to do something like this:

<template>
  <div id="TableHeaderDiv" class="TableHeaderClass">
    <table cellpadding="0" cellspacing="0" border="0">
      <thead>
        <tr>
          <div v-for="column in columns" v-bind:key="column">
            <th
              v-if="!column.isControl"
              @click="sortBy(column.DataField)"
              :class="{ active: sortKey == column.DataField }"
              :style="{ width: column.Width }"
            >
              {{ column.DisplayText }}
              <div v-if="!column.isControl">
                <span
                  class="arrow"
                  :class="sortOrders[column.DataField] > 0 ? 'asc' : 'dsc'"
                ></span>
              </div>
            </th>
            <th v-else :style="{ width: column.Width }">
              {{ column.DisplayText }}
            </th>
          </div>
        </tr>
      </thead>
    </table>
  </div>
</template>

But this just created a handful of <div> elements which is not what I intend to do.

Perhaps I am missing a fundamental concept with conditional rendering. Any help is much appreciated!

1
  • If you need an extra 'element' to hold a v-for or v-if use <template>. It will be omitted from the resulting DOM. Commented Jul 20, 2019 at 17:28

1 Answer 1

2

If you are using Vue.js 2.6 or higher you can pass null to the @click directive, and thus click listener will not be bound.

More details can be found in this RFC. Conveniently, if the argument value is null, the binding/listener will be removed.

So your code could look something like this: v-on="{ [!colum.isControl ? 'click' : null]: sortBy(column.DataField) }"

Sign up to request clarification or add additional context in comments.

3 Comments

The code provided will still add a click listener it just won't do anything. The RFC is referring to the ability to make the argument null, i.e. v-on:[null]=....
An attribute name can't contain spaces: see the drawbacks section of the RFC. I think your original code was fine it just wasn't related to the RFC. If avoiding creating the listener at all was really important I'd probably favour using v-on with an object instead.
i think it would be simpler to just do this: @click="!column.isControl ? sortBy(column.DataField) : null.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.