带有Vuetify数据表的动态可编辑列

发布于 2025-02-11 12:34:52 字数 5763 浏览 0 评论 0原文

我正在尝试制作一个VUE数据表组件,我想制作它,以便如果您传递了一系列列名,这些列中的值将像此示例。我目前正在尝试循环循环到将组件传递给组件的阵列prop ...

<template
   v-for="(column, index) in editableColumns"
   v-slot:[getEditableColumn(column)]="props"
>
    <v-edit-dialog
       :return-value.sync="props.item.desk"
       @save="save"
       @cancel="cancel"
       @open="open"
       @close="close"
       :key="index"
    >
          {{ props.item.desk }}
        <template v-slot:input>
            <v-text-field
              v-model="props.item.desk"
              label="Edit"
              single-line
              counter
            ></v-text-field>
        </template>
    </v-edit-dialog>
</template>

getable列的运行方式:

getEditableColumn(column) {
   console.log(column);
   return `item.${column}`;
},

它基本上返回了我想编辑的列的值。 /code>但该功能永远不会运行,我确实必须提到,如果我直接通过这样的名称而无需循环,但是我希望它能动态起作用,因为我将在具有不同列名称的多个位置使用该表,我不想让它们所有列可编辑。

下面我附上了组件的完整代码。

<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 template elements inside the component call to render custom components inside the table -->
      <template
        v-for="slot in Object.keys($scopedSlots)"
        :slot="slot"
        slot-scope="scope"
      >
        <slot :name="slot" v-bind="scope" />
      </template>
      <template
        v-for="(column, index) in editableColumns"
        v-slot:[getEditableColumn(column)]="props"
      >
        <v-edit-dialog
          :return-value.sync="props.item.desk"
          @save="save"
          @cancel="cancel"
          @open="open"
          @close="close"
          :key="index"
        >
          {{ props.item.desk }}
          <template v-slot:input>
            <v-text-field
              v-model="props.item.desk"
              label="Edit"
              single-line
              counter
            ></v-text-field>
          </template>
        </v-edit-dialog>
      </template>
    </v-data-table>
  </v-card>
</template>

<script>
import { utils, writeFile } from "xlsx";

export default {
  props: {
    headers: Array,
    data: Array,
    title: String,
    height: String,
    itemsPerPage: Number,
    itemKey: String,
    searchBar: { tpye: Boolean, default: false },
    rowClickFunction: {
      type: Function,
      default: () => {},
    },
    editableColumns: {
      type: Array,
    },
    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,
    };
  },

  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);
    },

    getEditableColumn(column) {
      console.log(column);
      return `item.${column}`;
    },

    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>

I am trying to make a vue data table component, I want to make it so that if you pass an array of column names, the values in those columns will be editable like in this example. I am currently trying to loop through the array prop passed to the component like as so...

<template
   v-for="(column, index) in editableColumns"
   v-slot:[getEditableColumn(column)]="props"
>
    <v-edit-dialog
       :return-value.sync="props.item.desk"
       @save="save"
       @cancel="cancel"
       @open="open"
       @close="close"
       :key="index"
    >
          {{ props.item.desk }}
        <template v-slot:input>
            <v-text-field
              v-model="props.item.desk"
              label="Edit"
              single-line
              counter
            ></v-text-field>
        </template>
    </v-edit-dialog>
</template>

the get editable columns operates as such:

getEditableColumn(column) {
   console.log(column);
   return `item.${column}`;
},

it basically returns the value of the column I want to be editable as such item.columnName but the function never runs, I do have to mention that if I pass directly the name like this without a for loop it works, but I want this to work dynamically as I will use the table in multiple places with different column names, and I don't want to make them all columns editable editable.

Below I have attached the full code of the component.

<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 template elements inside the component call to render custom components inside the table -->
      <template
        v-for="slot in Object.keys($scopedSlots)"
        :slot="slot"
        slot-scope="scope"
      >
        <slot :name="slot" v-bind="scope" />
      </template>
      <template
        v-for="(column, index) in editableColumns"
        v-slot:[getEditableColumn(column)]="props"
      >
        <v-edit-dialog
          :return-value.sync="props.item.desk"
          @save="save"
          @cancel="cancel"
          @open="open"
          @close="close"
          :key="index"
        >
          {{ props.item.desk }}
          <template v-slot:input>
            <v-text-field
              v-model="props.item.desk"
              label="Edit"
              single-line
              counter
            ></v-text-field>
          </template>
        </v-edit-dialog>
      </template>
    </v-data-table>
  </v-card>
</template>

<script>
import { utils, writeFile } from "xlsx";

export default {
  props: {
    headers: Array,
    data: Array,
    title: String,
    height: String,
    itemsPerPage: Number,
    itemKey: String,
    searchBar: { tpye: Boolean, default: false },
    rowClickFunction: {
      type: Function,
      default: () => {},
    },
    editableColumns: {
      type: Array,
    },
    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,
    };
  },

  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);
    },

    getEditableColumn(column) {
      console.log(column);
      return `item.${column}`;
    },

    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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

森林很绿却致人迷途 2025-02-18 12:34:52

插槽名称必须是标题元素的值之一

The slot name must be one of the headers element's value

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文