You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Vuetify Data Table实现动态可编辑列的技术问题

Fixing Dynamic Editable Columns in Your Vuetify Data Table

Hey there, let's get your dynamic editable columns working properly. I noticed two main issues in your code that are causing the getEditableColumn function to not run and your slots to fail:


1. Vue 2's Restriction on Dynamic Slot Names

In Vue 2, the value for v-slot:[...] needs to be a reactive property or a template-parsable expression. Calling a function directly inside the slot binding won't trigger during template compilation—that's why your getEditableColumn function never runs. Instead, we can directly use a template string in the slot binding to generate the correct item.columnName format.

2. Hardcoded Data Field

You had props.item.desk hardcoded everywhere in your edit dialog, which means all editable columns would modify the same desk field regardless of which column you're editing. We need to dynamically bind the field using the column value from your loop.


Updated Full Code

Template Section

Here's the fixed template with dynamic slot bindings and proper field references:

<template>
  <v-card>
    <v-card-title>
      {{ title || "" }}
      <v-col>
        <v-btn icon color="black" v-if="refresh">
          <v-icon>mdi-refresh</v-icon>
        </v-btn>
        <v-btn icon color="black" v-if="exportExcel" @click="exportToXlsx">
          <v-icon>mdi-microsoft-excel</v-icon>
        </v-btn>
        <v-btn icon color="black" v-if="exportPdf">
          <v-icon>mdi-file-pdf-box</v-icon>
        </v-btn>
        <v-btn icon color="black" v-if="fontSizeControlls">
          <v-icon>mdi-format-font-size-decrease</v-icon>
        </v-btn>
        <v-btn icon color="black" v-if="fontSizeControlls" @click="logSelected">
          <v-icon>mdi-format-font-size-increase</v-icon>
        </v-btn>
      </v-col>
      <v-spacer></v-spacer>
      <v-col v-if="searchBar">
        <v-text-field v-model="search" append-icon="mdi-magnify" label="Search" outlined dense ></v-text-field>
      </v-col>
    </v-card-title>
    <v-data-table 
      @input="(selected) => $emit('selected', selected)" 
      @click:row="rowClickFunction" 
      v-model="selected" 
      :headers="headers" 
      :items="data" 
      :search="search" 
      :show-select="showSelect" 
      :single-select="singleSelect" 
      :height="height" 
      :items-per-page="itemsPerPage" 
      :item-key="itemKey" 
      dense 
    >
      <!-- Pass through external slots -->
      <template v-for="slot in Object.keys($scopedSlots)" :slot="slot" slot-scope="scope" >
        <slot :name="slot" v-bind="scope" />
      </template>

      <!-- Dynamically generate editable column slots -->
      <template 
        v-for="(column, index) in editableColumns" 
        v-slot:[`item.${column}`]="props"
        :key="index"
      >
        <v-edit-dialog 
          :return-value.sync="props.item[column]" 
          @save="save" 
          @cancel="cancel" 
          @open="open" 
          @close="close"
        >
          {{ props.item[column] }}
          <template v-slot:input>
            <v-text-field 
              v-model="props.item[column]" 
              label="Edit" 
              single-line 
              counter 
            ></v-text-field>
          </template>
        </v-edit-dialog>
      </template>
    </v-data-table>
  </v-card>
</template>

Script Section

I cleaned up the script, fixed a few typos, and added missing properties to prevent errors:

<script>
import { utils, writeFile } from "xlsx";
export default {
  props: {
    headers: Array,
    data: Array,
    title: String,
    height: String,
    itemsPerPage: Number,
    itemKey: String,
    searchBar: {
      type: Boolean, // Fixed typo: was "tpye"
      default: false
    },
    rowClickFunction: {
      type: Function,
      default: () => {},
    },
    editableColumns: {
      type: Array,
      default: () => [] // Added default empty array to avoid loop errors
    },
    refresh: {
      type: Boolean,
      default: false,
    },
    exportExcel: {
      type: Boolean,
      default: false,
    },
    exportPdf: {
      type: Boolean,
      default: false,
    },
    fontSizeControlls: {
      type: Boolean,
      default: false,
    },
    singleSelect: {
      type: Boolean,
      default: false,
    },
    showSelect: {
      type: Boolean,
      default: false,
    },
    xlsxName: {
      type: String,
      default: "Sheet.xlsx",
    },
  },
  data() {
    return {
      search: "",
      selected: [],
      dialog: false,
      snack: false, // Added missing snack state variables
      snackColor: "",
      snackText: ""
    };
  },
  methods: {
    exportToXlsx() {
      const worksheet = utils.json_to_sheet(this.data);
      const workbook = utils.book_new();
      utils.book_append_sheet(workbook, worksheet, "Data");
      writeFile(workbook, this.xlsxName);
    },
    logSelected() {
      console.log(this.selected);
    },
    logRow(row) {
      console.log(row);
      console.log(this.selected);
    },
    getSlotName(slot) {
      return `${slot}.slotName`;
    },
    save() {
      this.snack = true;
      this.snackColor = "success";
      this.snackText = "Data saved";
    },
    cancel() {
      this.snack = true;
      this.snackColor = "error";
      this.snackText = "Canceled";
    },
    open() {
      this.snack = true;
      this.snackColor = "info";
      this.snackText = "Dialog opened";
    },
    close() {
      console.log("Dialog closed");
    },
  },
};
</script>

Key Fixes & Improvements

  • Dynamic Slot Names: Replaced the function call with a template string v-slot:[item.${column}] which Vue 2 can properly parse
  • Dynamic Field Binding: Changed all instances of props.item.desk to props.item[column] so each editable column targets the correct field
  • Typo Fix: Corrected tpye to type in the searchBar prop
  • Default Value: Added a default empty array for editableColumns to prevent errors when the prop isn't passed
  • Missing State: Added snack, snackColor, and snackText to the data object—these were referenced in your methods but weren't defined, which would have caused runtime errors

Now when you pass an array like ['name', 'age', 'desk'] to the editableColumns prop, those columns will automatically become editable with the correct field bindings.

内容的提问来源于stack exchange,提问作者Vlad Tanase

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 01:32:29