最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to highlight rows in v-data-table on click in Vuetify (version >= 2.0)? - Stack Overflow

programmeradmin2浏览0评论

I use a v-data-table to manage emails. User can click on a row and a popup appears with the email details.

What I want to have:
I want to have rows marked as "readed" (so css bold/not-bold) after these rows were clicked.

Problem:
I already found some examples here (but only for older Vuetify versions): Vuetify - How to highlight row on click in v-data-table

This example (and all other examples I've found) use extended code for v-data-table - like:

<v-data-table :headers="headers" :items="desserts" class="elevation-1">
  <template v-slot:items="props">
    <tr @click="activerow(props.item)" :class="{'primary': props.item.id===selectedId}">
      <td>{{ props.item.name }}</td>
      <td class="text-xs-right">{{ props.item.calories }}</td>
      <td class="text-xs-right">{{ props.item.fat }}</td>
      <td class="text-xs-right">{{ props.item.carbs }}</td>
      <td class="text-xs-right">{{ props.item.protein }}</td>
      <td class="text-xs-right">{{ props.item.iron }}</td>
    </tr>
  </template>
</v-data-table>

So extended code is:

<template v-slot:items="props">
  <tr @click="activerow(props.item)" :class="{'primary': props.item.id===selectedId}">
    <td>{{ props.item.name }}</td>
    <td class="text-xs-right">{{ props.item.calories }}</td>
    <td class="text-xs-right">{{ props.item.fat }}</td>
    <td class="text-xs-right">{{ props.item.carbs }}</td>
    <td class="text-xs-right">{{ props.item.protein }}</td>
    <td class="text-xs-right">{{ props.item.iron }}</td>
  </tr>
</template>

However since I use Vutify version 2 the

<template slot="headers" slot-scope="props"> and <template slot="items" slot-scope="props"> inside <v-data-table> seem to be ignored.

Vuetify 2 provides some new slots, but I have not yet find out how to use them for this example.

Can anyone provide an example for Vuetify >= 2.0? Believe me, there is no one for higher versions available yet - not on any development environment like CodePen or JSFiddle etc.

I use a v-data-table to manage emails. User can click on a row and a popup appears with the email details.

What I want to have:
I want to have rows marked as "readed" (so css bold/not-bold) after these rows were clicked.

Problem:
I already found some examples here (but only for older Vuetify versions): Vuetify - How to highlight row on click in v-data-table

This example (and all other examples I've found) use extended code for v-data-table - like:

<v-data-table :headers="headers" :items="desserts" class="elevation-1">
  <template v-slot:items="props">
    <tr @click="activerow(props.item)" :class="{'primary': props.item.id===selectedId}">
      <td>{{ props.item.name }}</td>
      <td class="text-xs-right">{{ props.item.calories }}</td>
      <td class="text-xs-right">{{ props.item.fat }}</td>
      <td class="text-xs-right">{{ props.item.carbs }}</td>
      <td class="text-xs-right">{{ props.item.protein }}</td>
      <td class="text-xs-right">{{ props.item.iron }}</td>
    </tr>
  </template>
</v-data-table>

So extended code is:

<template v-slot:items="props">
  <tr @click="activerow(props.item)" :class="{'primary': props.item.id===selectedId}">
    <td>{{ props.item.name }}</td>
    <td class="text-xs-right">{{ props.item.calories }}</td>
    <td class="text-xs-right">{{ props.item.fat }}</td>
    <td class="text-xs-right">{{ props.item.carbs }}</td>
    <td class="text-xs-right">{{ props.item.protein }}</td>
    <td class="text-xs-right">{{ props.item.iron }}</td>
  </tr>
</template>

However since I use Vutify version 2 the

<template slot="headers" slot-scope="props"> and <template slot="items" slot-scope="props"> inside <v-data-table> seem to be ignored.

Vuetify 2 provides some new slots, but I have not yet find out how to use them for this example.

Can anyone provide an example for Vuetify >= 2.0? Believe me, there is no one for higher versions available yet - not on any development environment like CodePen or JSFiddle etc.

Share Improve this question edited Feb 10, 2020 at 8:30 ouflak 2,50810 gold badges45 silver badges52 bronze badges asked Aug 14, 2019 at 7:39 VarathronVarathron 911 gold badge1 silver badge3 bronze badges 3
  • You might be able to use the click:row event, but if you want to persist the clicked state when you refresh the page, you might need to use the v-slot solution. – Flame Commented Aug 14, 2019 at 11:30
  • Hi Flame, i use also click:row but without an solution yet. It would be great if you could provide a workable excample in CodePen. – Varathron Commented Aug 14, 2019 at 13:48
  • Try something along the lines of: @click="$event.target.classList.add('clicked')" to add a clicked class to the element you just clicked – Flame Commented Aug 14, 2019 at 13:52
Add a comment  | 

3 Answers 3

Reset to default 10

For me it workes with Vuetify 2.X by replacing the table body (v-slot:body) and define the tr and td manually. It helps to study the Slot Example.

This way it is possible to add the click event and set the css class like this:

<template v-slot:body="{ items }">
    <tbody>
      <tr v-for="item in items" :key="item.name" @click="selectItem(item)" :class="{'selectedRow': item === selectedItem}">
        <td>{{ item.name }}</td>
        <td>{{ item.age }}</td>
      </tr>
    </tbody>
</template>

(Side note: This way you can not use the event click:row on the v-data-table anymore. Because it does not get fired by overwriting the row... But defining @click directly on tr works nicely too.)

In method selectItem we save the item in a data field selectedItem.

data () {
  return {
    selectedItem: null,
    ...
  }
},
methods: {
    selectItem (item) {
      console.log('Item selected: ' + item.name)
      this.selectedItem = item
    }
}

CSS class we set when the row is clicked. So background changes and text gets bold:

<style scoped>
.selectedRow {
    background-color: red;
    font-weight: bold;
}
</style>

I have added method selectRow that receives an item, and adds isSelected property to it. Then in template I assign class .primary if item has property isSelected.

Notice: this methods also removes isSelected property from previous selected item. so that only one <tr> can be highlighted at the same time.

new Vue({
  el: "#app",
  methods: {
    selectRow(item) {
      // remove isSelected from already selected item
      // const prevItem = this.desserts.find(dessert => dessert.isSelected);
      // if (prevItem) this.$delete(prevItem, 'isSelected');
      this.$set(item, "isSelected", true)
    }
  },
  data() {
    return {
      headers: [{
          text: 'Dessert (100g serving)',
          align: 'left',
          sortable: false,
          value: 'name'
        },
        {
          text: 'Calories',
          value: 'calories'
        },
        {
          text: 'Fat (g)',
          value: 'fat'
        },
        {
          text: 'Carbs (g)',
          value: 'carbs'
        },
        {
          text: 'Protein (g)',
          value: 'protein'
        },
        {
          text: 'Iron (%)',
          value: 'iron'
        }
      ],
      desserts: [{
          name: 'Frozen Yogurt',
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0,
          iron: '1%'
        },
        {
          name: 'Ice cream sandwich',
          calories: 237,
          fat: 9.0,
          carbs: 37,
          protein: 4.3,
          iron: '1%'
        },
        {
          name: 'Eclair',
          calories: 262,
          fat: 16.0,
          carbs: 23,
          protein: 6.0,
          iron: '7%'
        },
        {
          name: 'Cupcake',
          calories: 305,
          fat: 3.7,
          carbs: 67,
          protein: 4.3,
          iron: '8%'
        },
        {
          name: 'Gingerbread',
          calories: 356,
          fat: 16.0,
          carbs: 49,
          protein: 3.9,
          iron: '16%'
        },
        {
          name: 'Jelly bean',
          calories: 375,
          fat: 0.0,
          carbs: 94,
          protein: 0.0,
          iron: '0%'
        },
        {
          name: 'Lollipop',
          calories: 392,
          fat: 0.2,
          carbs: 98,
          protein: 0,
          iron: '2%'
        },
        {
          name: 'Honeycomb',
          calories: 408,
          fat: 3.2,
          carbs: 87,
          protein: 6.5,
          iron: '45%'
        },
        {
          name: 'Donut',
          calories: 452,
          fat: 25.0,
          carbs: 51,
          protein: 4.9,
          iron: '22%'
        },
        {
          name: 'KitKat',
          calories: 518,
          fat: 26.0,
          carbs: 65,
          protein: 7,
          iron: '6%'
        }
      ]
    }
  },
})
.primary,
.primary:hover {
  /** avoid using !important, added just for example**/
  background-color: red !important;
}

.as-console-wrapper {
  display: none !important;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
  <v-data-table :headers="headers" :items="desserts" class="elevation-1">
    <template v-slot:items="props">
        <tr @click="selectRow(props.item)" :class="{ 'primary': props.item.isSelected }">
        <td>{{ props.item.name }}</td>
        <td>{{ props.item.calories }}</td>
        <td>{{ props.item.fat }}</td>
        <td>{{ props.item.carbs }}</td>
        <td>{{ props.item.protein }}</td>
        <td>{{ props.item.iron }}</td>
        </tr>
      </template>
  </v-data-table>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>

I know this is a bit old question, but you can use vuetify's item-class and @click:row properties to handle row click and set custom row class.

发布评论

评论列表(0)

  1. 暂无评论