0
votes

I writing bootstrap component for inline edititng in table
I noticed that slots have priority: cell(%cell%) above cell()

How can I turn off a v-slot:cell(%cell%) for a specific row in a table?

<b-table ...>
    <template v-slot:cell()="data">
        <b-input
            v-if="data.item.editing && data.field.editable"
            v-model="tableData[data.index][data.field.key]"
        />
        <span v-else>{{data.value}}</span>
    </template>

    <template
        v-for="(_, slot) of $scopedSlots"
        v-slot:[slot]="scope"
    >
        <slot
            name="cell()"
            v-bind="scope"
        />
    </template>
<b-table>
1
Could you provide some details about the use-case?Hiws
Of course codepen.io/blogaster/pen/abNyRYZ I want edit data in tableblogaster
Hah, that's funny. I created that codepen. I understand that you to edit certain columns. But why do you want to disable certain slots on specific rows?Hiws
If there is a slot for the line, then I cannot influence it through the edit slot. You got my idea rightblogaster
So you want a slot for the displayed value when that field is not being edited. Am i understanding that correctly?Hiws

1 Answers

1
votes

If I'm understanding correctly, you want to be able to have a slot to customize the layout when the field is not being editted.

For this you will have to create your own component, wrapping <b-table>, and create your own slot.

<template v-slot:cell()="data">
    <b-input
      v-if="data.item.editing && data.field.editable"
      v-model="tableData[data.index][data.field.key]"
    />
  <span v-else>
    <slot :name="`noedit(${data.field.key})`" v-bind="data">
      {{ data.value }}
    </slot>
  </span>
</template>

The above code, will then allow you to use the slot noedit(field_key) (you can change the slot name to whatever you want), to edit the layout when that field is not in an "editing" state.

Example

Vue.component("data-table", {
  template: "#data-table",
  computed: {
    editableFields() {
      return this.fields.filter((field) => field.editable);
    }
  },
  data() {
    return {
      userRow: null
    };
  },
  props: ["items", "fields"],
  methods: {
    editUser(user) {
      let doEdit = true;
      if (
        this.userRow &&
        !confirm("You have unsaved changes, are you sure you want to continue?")
      ) {
        doEdit = false;
      }

      if (doEdit) {
        this.userRow = { ...user };
      }
    },
    saveEdit() {
      let user = this.items.find((u) => u.id === this.userRow.id);
      Object.assign(user, this.userRow);

      this.resetEdit();
    },
    resetEdit() {
      this.userRow = null;
    }
  }
});

new Vue({
  el: "#app",
  data() {
    return {
      fields: [
        { key: "id" },
        { key: "first_name", editable: true },
        { key: "last_name", editable: true },
        { key: "age", editable: true, type: "number", isNumber: true },
        { key: "actions" }
      ],
      items: [
        { id: 1, first_name: "Mikkel", last_name: "Hansen", age: 56 },
        { id: 2, first_name: "Mads", last_name: "Mikkelsen", age: 39 },
        { id: 3, first_name: "Anders", last_name: "Matthesen", age: 42 }
      ]
    };
  }
});
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.js"></script>


<div id="app">
  <data-table :items="items" :fields="fields">
    <template v-slot:noedit(first_name)="{ value }">
      <b class="text-primary">
        {{ value }}
      </b>
    </template>

    <template v-slot:cell(id)="{ value }">
      <i class="text-danger">{{ value }}</i>
    </template>
  </data-table>
</div>

<template id="data-table">
  <b-table :items="items" :fields="fields">
    <template v-for="field in editableFields" v-slot:[`cell(${field.key})`]="s">
      <b-input v-if="userRow && userRow.id === s.item.id" v-model="userRow[s.field.key]" :type="s.field.type || 'text'" :number="s.field.isNumber">
      </b-input>
      <template v-else>
        <slot :name="`noedit(${s.field.key})`" v-bind="s">
          {{ s.value }}
        </slot>
      </template>
    </template>

    <template v-slot:cell(actions)="{ item }">
      <b-button-group v-if="userRow && userRow.id === item.id">
        <b-btn variant="success" @click="saveEdit">
          Save
        </b-btn>
        <b-btn variant="danger" @click="resetEdit">
          Cancel
        </b-btn>
      </b-button-group>
      <b-btn v-else variant="primary" @click="editUser(item)">
        Edit
      </b-btn>
    </template>

    <!-- Pass in slots from parent -->
    <template v-for="name in Object.keys($scopedSlots)" v-slot:[name]="scope">
      <slot :name="name" v-bind="scope"></slot>
    </template>
  </b-table>
</template>