vue.jsvuetify.jsv-data-table

Vuetify : Editable cell for v-data-table in specified column only


I have this simple record in vuetify using v-data-table.

enter image description here

I'm making an editable cell for adding data. So once you clicked any column cell, a popup edit will appear to edit the data.

But, I don't want the user to edit this on this No and Name column, because it is a fixed data.

All I want is to edit only this Result column(adding data in cell). enter image description here

How could I achieve that function?

Codepen

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
        headers: [{text: 'No', sortable: false, value: 'number'},
              {text: 'Name', sortable: false, value: 'name'},
              {text: 'Result', sortable: false, value:'result'}],
        records: [{name:'data 1'},{name:'data 2'},{name:'data 3'}],
    }
  },
  computed: {
    itemsWithIndex() {
      return this.records.map(
        (records, index) => ({
          ...records,
          number: index + 1
        }))
    }
  }
})
#app {
  padding: 1rem;
}

#table-card {
  padding: 2rem;
}
<head>
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vuetify/2.1.12/vuetify.min.css" />
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/2.1.12/vuetify.min.js"></script>
</head>

<div id="app">
    <v-app>
        <v-card id="table-card">
        <h3>Records</h3>
        <v-data-table
            :headers="headers"
            :items="itemsWithIndex"/>
        <template
        v-for="header in headers"
        v-slot:[`item.${header.value}`]="props"
        >
        <v-edit-dialog
            :key="header.value"
            :return-value.sync="props.item[header.value]"
        >
            {{ props.item[header.value] }}
            <template v-slot:input>
            <v-text-field
                v-model="props.item[header.value]"
                label="Edit"
                single-line
            ></v-text-field>
            </template>
        </v-edit-dialog>
        </template>
        </v-card>
    </v-app>
</div>


Solution

  • Currently, you are setting an edit dialog on all cells:

    <template
      v-for="header in headers"
      v-slot:[`item.${header.value}`]="props"
    >
      <v-edit-dialog
        :key="header.value"
        :return-value.sync="props.item[header.value]"
      >
    ...
    

    Instead, set it only on the result column:

    <template v-slot:item.result="{item, header}">
      <v-edit-dialog
        :key="header.value"
        :return-value.sync="item[header.value]"
      >
    ...
    

    Alternatively, if you only want to exclude a few columns, leave the v-for, but have it iterate a filtered list of headers.

    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      data() {
        return {
            headers: [{text: 'No', sortable: false, value: 'number'},
                  {text: 'Name', sortable: false, value: 'name'},
                  {text: 'Result', sortable: false, value:'result'}],
            records: [{name:'data 1'},{name:'data 2'},{name:'data 3'}],
        }
      },
      computed: {
        itemsWithIndex() {
          return this.records.map(
            (records, index) => ({
              ...records,
              number: index + 1
            }))
        }
      }
    })
    #app {
      padding: 1rem;
    }
    
    #table-card {
      padding: 2rem;
    }
    <head>
     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vuetify/2.1.12/vuetify.min.css" />
     <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/2.1.12/vuetify.min.js"></script>
    </head>
    
    <div id="app">
        <v-app>
            <v-card id="table-card">
            <h3>Records</h3>
            <v-data-table
                :headers="headers"
                :items="itemsWithIndex"/>
            <template v-slot:item.result="{item, header}">
            <v-edit-dialog
                :key="header.value"
                :return-value.sync="item[header.value]"
            >
                {{ item[header.value] }}
                <template v-slot:input>
                <v-text-field
                    v-model="item[header.value]"
                    label="Edit"
                    single-line
                ></v-text-field>
                </template>
            </v-edit-dialog>
            </template>
            </v-card>
        </v-app>
    </div>