Hide a button generated from v-for in a table in VueJS

  Kiến thức lập trình

I want to hide a button from a table. In the component there is a v-for looping in a table. In my response the button display two states (Cancel and Retake Snapshot buttons). I want to set a rule to only hide the Retake Snapshot button.

Here is a breakdown of my code

  1. Component holding the text of the button called clickableText
<template>
  <div class="clickable-text" @click="() => !disabled && onClick()">
    <div :class="className">{{ text }}</div>
  </div>
</template>

<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator';
@Component({})
export default class ClickableText extends Vue {
  @Prop({ default: true }) text: string;
  @Prop({ default: true }) clickable: boolean;
  @Prop({ default: () => {} }) onClick: () => void;

  get className() {
    return {
      disabled: this.disabled,
      clickable: this.clickable && !this.disabled,
    };
  }
}
</script>
  1. ClickableText is called here in a component called ClickableTexts
<template>
  <div v-for="(item, id) in items" :key="id">
    <ClickableText v-bind="item" />
  </div>
</template>

<script lang="ts">
import ClickableText from './ClickableText.vue';
@Component({})
export default class ClickableTexts extends Vue {
  @Prop() items: {
    text: string;
    disabled: boolean;
    classes: string;
    clickable: boolean;
    loading?: boolean;
    onClick: () => void;
  }[];
}
</script>
  1. ClickableTexts is now called in a component called AppTable
<table class="table__wrapper">
      <thead class="table__headers mb-4">
        <tr>
          <th v-for="header in headers" :key="header.value" class="" :class="{ clickable: header.sortable }">
            <div class="d-flex align-center" @click="headerClicked(header)">
              {{ header.text }}
            </div>
          </th>
        </tr>
      </thead>
      <tbody class="table__items">
        <tr v-for="(item, n) in items" :key="n" data-qa="row" :id="item.id ? item.id.value : n" class="table__row">
          <td v-for="header in headers" :key="header.value" :data-qa="header.value">
            <div :class="itemClass(item, header)" @click="itemClicked(item, header)">
              <div v-if="item[header.value] && item[header.value].value">{{ item[header.value].value }}</div>
              <div v-else>
                <component :is="item[header.value].component" v-bind="item[header.value].props" :disabled="isLastOrSingleItem(n)" v-show="hasValidateGowker" />
              </div>
            </div>
          </td>
        </tr>
      </tbody>
    </table>

<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator';
import { TableHeader, TableItem, TablePagination, AppTableItemClick } from './interfaces';

@Component
export default class AppTable extends Vue {
  @Prop() headers: TableHeader[];
  @Prop() items: TableItem[];
@Prop({ default: false }) hasValidateGowker: boolean;

  isLastOrSingleItem(index: number): boolean {
    return index === this.items.length - 1 || this.items.length === 1;
  }

  itemClicked(item: TableItem, header: TableHeader): AppTableItemClick | undefined {
    const headerName = header.value;
    if (item[headerName]?.clickable) {
      const returnValue = { item, id: headerName };
      this.$emit('itemClicked', returnValue);
      item[headerName]?.onClick?.();
      return returnValue;
    }
  }
}
</script>

THIS IS WHERE THE BUTTONS ARE SHOWING
<component :is="item[header.value].component" v-bind="item[header.value].props" :disabled="isLastOrSingleItem(n)" v-show="hasValidateGowker" />

AND THE RESPONSE IS AS BELOW if I do {{item[header.value].props}}
{ "items": [ { "classes": "action-text ", "disabled": false, "text": "Cancel", "clickable": true, "show": true }, { "classes": "action-text", "disabled": false, "loading": false, "text": "Retake Snapshot", "clickable": true, "show": true } ] }

  1. Finally AppTable is called in this component
<AppTable
   v-if="hasSnapshots && !loadingSnapshots"
   :headers="headers"
   :items="items"
   @itemClicked="onItemClick"
   @headerClicked="onHeaderClick"
   :hasValidateGowker="hasValidateGowker"
/>

<script lang="ts">
export default class SnapshotController extends Vue {
  get hasValidateGowker() {
    return modules.user.hasPermission(UserPermissions.ValidateGowker);
  }
</script>

hasValidateGowker() hides both buttons unfortunately.

LEAVE A COMMENT