Vuetify Labs: using slots for icons in VDataTable - javascript

I want to render an icon in a column of a VDataTable. Did anyone figure out, if it is already possible to use slots for VDataTable in the latest Lab release of Vuetify3.
With Vuetify Version 2.x it could be done like that:
<template>
<v-data-table
:headers="headers"
:items="tableData"
:items-per-page="10"
>
<template #[`item.actions`]="{ item }">
<v-icon
icon="$magnifier"
style="color: #0692bc"
class="inline cursor-pointer mr-4"
#click="action(item)"
/>
</template>
</v-data-table>
</template>
<script>
export default {
data: () => ({
tableData: [
{
test_data: 123,
},
],
headers: [
{
title: 'Funktion',
value: 'actions',
sortable: false,
},
],
}),
methods: {
action(item) {
console.log(item.test_data);
},
},
};
</script>
That results in an empty column (no Errors, Warnings as its not ready for production yet).
EDIT:
Just solved it, it is now key instead of value in the header objects. So the headers should be:
headers: [
{
title: 'Funktion',
key: 'actions',
sortable: false,
},
],

It is possible according to the documentation. It can be done like this-
<template v-slot:item.actions="{ item }">
<v-icon
icon="$magnifier"
style="color: #0692bc"
class="inline cursor-pointer mr-4"
#click="action(item)"
/>
</template>

Related

How to make some of the columns of the table to contain a dropdown box to filter the table?

I'm using VueJs and Vuetify. I have Vuetify's table where I present the data. I'm trying to edit the header column of some of the columns so I could add a dropdown search bar to filter the table. Something like:
Where Select Item is actually the header (please see the sort symbol aside of it). I could add it the dropdown above the table, like it's shown in the official docs, but I'm trying to make the dropdown as the header column itself and not just above the table.
The current code:
<v-data-table
class="elevation-1"
:headers="headers"
:items="items"
:items-per-page="tableItemsPerPage"
:footer-props="tableFooterSettings"
:loading="tableLoading"
hide-default-footer
>
where headers is a simple array of the headers, for example:
{ text: 'data', value: 'pretty_data', align: 'center', sortable: true },
Of course I want the column to be still sortable (like it's shown in the image [the arrow]). How can I make it done?
Created this working Demo. Hope it will work as per your expectation.
new Vue({
el: '#app',
data: () => ({
selected: [],
headers: [
{
text: 'Name',
align: 'left',
value: 'name'
}
],
filters: {
name: []
},
desserts: [
{
name: 'Frozen Yogurt'
},
{
name: 'Ice cream sandwich'
},
{
name: 'Eclair'
},
{
name: 'Cupcake'
},
{
name: 'Gingerbread'
},
{
name: 'Jelly bean'
},
{
name: 'Lollipop'
},
{
name: 'Honeycomb'
},
{
name: 'Donut'
},
{
name: 'KitKat'
}
]
}),
computed: {
filteredDesserts() {
return this.desserts.filter(d => {
return Object.keys(this.filters).every(f => {
return this.filters[f].length < 1 || this.filters[f].includes(d[f])
})
})
}
},
methods: {
columnValueList(val) {
return this.desserts.map(d => d[val])
}
}
})
<script src="https://unpkg.com/vue#2.6.14/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.1.10/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.1.10/dist/vuetify.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<v-data-table
v-model="selected"
:headers="headers"
:items="filteredDesserts"
item-key="name"
class="elevation-1"
>
<template slot="headers" slot-scope="props">
<tr class="grey lighten-3">
<th
v-for="header in props.headers"
:key="header.text"
>
<div v-if="filters.hasOwnProperty(header.value)">
<v-select flat hide-details small multiple clearable :items="columnValueList(header.value)" v-model="filters[header.value]">
</v-select>
</div>
</th>
</tr>
</template>
<template slot="items" slot-scope="props">
<tr>
<td>{{ props.item.name }}</td>
</tr>
</template>
</v-data-table>
</v-app>
</div>

How do I store data from v-form into the data prop?

I am developing a login screen it currently looks like this:
I am using vue tabs and for the input I am using v-form boxes. I am generating these components with the following HTML:
<template>
<div>
<div id="app">
<v-app id="inspire">
<v-card width="30%" class="mx-auto mt-5">
<v-card-title width="100%">
<v-tabs
v-model="tab"
fixed-tabs
>
<v-tab
v-for="item in items"
:key="item.tab"
>
{{ item.tab }}
</v-tab>
</v-tabs>
<v-tabs-items v-model="tab">
<v-tab-item
v-for="item in items"
:key="item.tab"
>
<v-card flat width="400px">
<v-card-text>
<v-form
v-for="form in item.content.forms"
:key="form.name"
>
<v-text-field
:label=form.name
:type=form.type
:placeholder=form.placeholder
:v-model=form.model
>
</v-text-field>
</v-form>
{{ message }}
<v-btn elevation= "100" color= "blue" top :style="{left: '42%', transform:'translateX(-50%)'}" #click="buttonPressed(item.content.createAccount, item.content)">{{item.content.buttonText}}</v-btn>
</v-card-text>
</v-card>
</v-tab-item>
</v-tabs-items>
</v-card-title>
</v-card>
</v-app>
</div>
</div>
</template>
The card is generated via the HTML above which references this data() prop:
data () {
return {
tab: null,
items: [
{
tab: 'Login', content: {
forms: [
{name: "Email", type:"text", placeholder: "Email", model: ""},
{name: "Password", type: "password", placeholder: "Password", model: ""}
],
buttonText: "Login",
createAccount: false
} },
{
tab: 'Sign Up', content: {
forms: [
{name: "Display Name", type: "text", placeholder: "Display Name", model: ""},
{name: "Email", type:"text", placeholder: "Email", model: ""},
{name: "Password", type: "password", placeholder: "Password", model: ""}
],
buttonText: "SignUp",
createAccount: true
} }
],
}
}
My problem is specifically related (probably) to how the individual v-forms are storing the data within them. To store data I have attached each v-text-field via v-model prop in this line of code in the HTML section above:
:v-model=form.model
The problem I am having is that when I log the values to the debug window via this function in the script section of my file (the related interface is included for convenience):
interface DataFormat{
forms : [
{
name: string,
model: string
}
]
}
buttonPressed(createAccount: boolean, formList: DataFormat): void {
if(createAccount){
//SignUp
for(let form in formList.forms){
console.log(formList.forms[form].name + ": " + formList.forms[form].model);
}
}else{
//Login
for(let form in formList.forms){
console.log(form);
}
}
}
I get nothing but empty strings (for now I am only properly testing the sign up button). You can see in the top right corner the output from my console.logs in the buttonPressed function after hitting the button with the values "asd" in each field.
If you need access to more of my code to answer this question the github for this project is the following:
Github repo for my chat application (not currently using Socket_IO)
I just had to use v-model instead of :v-model
lol.

Buefy - Show array results as separated tags in table

I'm retrieving a data set that has a few fields as a list included. The results need to be shown in a Buefy table (https://buefy.org/documentation/table) and I would like to show the list items as separate tags (https://buefy.org/documentation/tag/) in the table cell.
The code below simulates the issue. The result of this is showing the data in the second column as plain text Value1,Value2,Value3.
Not only does this look bad, but because there are no spaces between the values, it makes the table too wide for the screen and other columns are not visible anymore because of it.
I would like it to look something like this in the List cell:
The code to reproduce:
<template>
<b-table :data="data" :columns="columns"></b-table>
</template>
<script>
export default {
data() {
return {
data: [
{ 'id': 1, 'list': ["Value1","Value2","Value3"] },
{ 'id': 2, 'list': ["Value1","Value2","Value3"] },
{ 'id': 3, 'list': ["Value1","Value2","Value3"] }
],
columns: [
{
field: 'id',
label: 'ID',
},
{
field: 'list',
label: 'List',
}
]
}
}
}
</script>
Try out the following custom rendering and add the class helper mr-2 to make space between tags :
<b-table :data="data">
<b-table-column field="id" label="ID" centered v-slot="props">
{{props.row.id}}
</b-table-column>
<b-table-column field="list" label="List" centered v-slot="props">
<span v-for="item in props.row.list" class="tag mr-2">
{{item}}
</span>
</b-table-column>
</b-table>
Live demo

Row selection and pagination - Vue

Using vue, I display my database in a table.
My table contains a lot of rows. Therefore, I use pagination.
Using the select function, I can select multiple rows and store them in an array.
The problem:
I select some rows in my table. The data from the row is stored in my array called selected. I let them appear next to my table.
Using pagination, I go to the next page. My data is still stored in this array. When I now select another row. My array is emptied,
my data from my section is gone.
How can I solve this? Why does this happen? Is there a way to store this data so it isn't lost?
Did I miss something?
Bellow, you find my code. Thanks for the help.
Vue code
<!-- Main table -->
<b-row align-v="start">
<b-col sm="8">
<b-table class="col-sm-12"
show-empty
striped hover
selectable
stacked="md"
:items="values"
:fields="fields"
:select-mode="selectMode"
:current-page="currentPage"
:filter="valueSearch"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
:sort-direction="sortDirection"
#filtered="onFiltered"
#row-selected="rowSelected"
<template slot="name" slot-scope="row">
{{row.item.name}}
</template>
<template slot="id" slot-scope="row">
{{ row.item.id }}
</template>
<template slot="ref" slot-scope="row">
{{row.item.ref}}
</template>
<template slot="specific" slot-scope="row">
{{row.item.specific}}
</template>
<template slot="iso" slot-scope="row">
{{row.item.iso}}
</template>
<template slot="tax" slot-scope="row">
{{row.item.tax}}
</template>
<template slot="amount" slot-scope="row">
<span class='dot largerSize' :class="statusColor[range(row.item.amount)]"></span>
</template>
</b-table>
</b-col>
<b-col sm="4">
Here comes the value selected.
<div v-for="selectedvalue in selected" :key="selectedvalue.id">
{{ selectedvalue.id }} - {{selectedvalue.name}}
{{selected}}
</div>
</b-col>
</b-row>
<!-- How is sorted? & Pagnation -->
<b-row align-v="end" class="mb-2">
<b-col>
Sorting By: <b>{{ sortBy | capitalize }}</b>, Sort Direction:
<b>{{ sortDesc ? 'Descending' : 'Ascending' }}</b>
</b-col>
<b-col>
<b-pagination v-model="currentPage" :total-rows="totalRows" :per-page="perPage" class="my-0"></b-pagination>
</b-col>
<b-col>One of three columns</b-col>
</b-row>
Javascript
<script>
export default {
props: ['valuedata','minamount','maxamount'],
data() {
return {
values: this.valuedata,
statusColor: ["red","orange","green"],
totalRows: 1,
currentPage: 1,
perPage: 10,
pageOptions: [5, 10, 20, 50,100],
sortBy: "id",
sortDesc: false,
sortDirection: 'asc',
filter: null,
selectMode: 'multi',
fixed: true,
selected: [],
fields: {
id: {
label: "Id",
sortable: true
},
name: {
label: "Name",
sortable: true
},
ref: {
label: "Ref",
sortable: true
},
iso: {
label: "Iso",
sortable: true
},
tax: {
label: "Tax",
sortable: true
},
specific: {
label: "specific",
sortable: true
},
amount: {
label: "amount",
sortable: true
}
}
}
},
computed:{
hits: function(){
var hits = this.values.length
return hits
}
},
mounted () {
this.totalRows = this.values.length
},
methods: {
onFiltered(filteredItems) {
// Trigger pagination to update the number of buttons/pages due to filtering
this.totalRows = filteredItems.length
this.currentPage = 1
},
// Option: enables the storage of selected rows
rowSelected(items){
console.log(items[0].name)
this.selected = items
},
// Function: color code amount
range: function(x){
if (x < this.minamount){
return 0;
}else if(x >= this.minamount && x <= this.maxamount ){
return 1;
}else if(x >= this.maxamount ){
return 2;
}
}
},
filters: {
// Function: captitalize the first letter
capitalize: function (value) {
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
}
From my understanding, you replace all items in selected :
// Option: enables the storage of selected rows
rowSelected(items){
console.log(items[0].name)
this.selected = items
},
What you want to do is adding values, not replacing them, so IMHO what you should is something like :
// Option: enables the storage of selected rows
rowSelected(items){
console.log(items[0].name)
items.forEach(item => {
const selectedIds = this.selected.map(selectedItem => selectedItem.id);
// I guess you don't want twice the same item in your array
if (!selectedIds.includes(item.id) {
this.selected.push(item)
}
})
},

How to use v-switches v-model with dynamic array in v-datatable

I'm using Vue.js with Vuetify and I'm trying to use v-data-table to load a list of menus from back end and set some permissions on it using v-switches but I am facing a problem while trying to v-model an array:
<v-data-table
:items="Menus"
class="elevation-1"
hide-actions
:headers="Menuheaders"
flat
>
<template slot="items" slot-scope="props">
<td><v-checkbox hide-details v-model="permissions.show" class="shrink mr-2"></v-checkbox></td>
<td>{{ props.item.name }}</td>
<td>
<v-switch
v-model="permissions.add"
></v-switch>
</td>
<td>
<v-switch
v-model="permissions.edit"
></v-switch>
</td>
<td>
<v-switch
v-model="permissions.delete"
></v-switch>
</td>
<td>
<v-switch
v-model="permissions.execute"
></v-switch>
</td>
</template>
</v-data-table>
permissions array is what im using in v-model for switches.
<script>
export default {
data() {
return {
Menus: [],
Menuheaders: [
{ text: 'Show', value: 'show' },
{
text: 'Name',
align: 'left',
sortable: false,
value: 'name'
},
{ text: 'Add', value: 'add' },
{ text: 'Edit', value: 'edit' },
{ text: 'Delete', value: 'delete' },
{ text: 'Execute', value: 'execute' },
],
Roles: [],
permissions : [
{
add : false,
edit : false,
delete : false,
show : false,
execute : false,
}
]
}
},
methods : {
loadMenus(){
axios.get("api/menu").then(({data}) => (this.Menus = data))
.then(()=>{
})
.catch(()=>{
})
},
loadRoles(){
axios.get("api/role").then(({data}) => (this.Roles = data))
.then(()=>{
})
.catch(()=>{
})
}
}
}
</script>
The problem is when I click on the switches they all take the same value
what im trying to do here is creating new role and assign permissions on each menu
try this code. after fetching data map each permission with each menu item.
[https://codepen.io/anon/pen/daBMaX?editors=1010]
<v-data-table
v-model="selected"
:headers="headers"
:items="desserts"
:single-select="singleSelect"
item-key="name"
show-select
class="elevation-1"
>
<template v-slot:top>
<v-switch
v-model="singleSelect"
label="Single select"
class="pa-3"
></v-switch>
</template>
</v-data-table>
For this kind of cases, there is single-select for Vuetify data-table

Categories