Individual v-selects for v-data-table rows - vue.js

I am trying to create a table that allows me to have one v-select for each row of the "available" column and to save whatever the user selects, being either "In stock" or "unavailable" for that column. How exactly do i do that with the following table that contains the following data?
Table:
<template>
<v-data-table
:headers="headers"
:items="desserts"
:items-per-page="5"
class="elevation-1"
>
<template slot="items" slot-scope="props">
<tr #click="props.expanded = !props.expanded">
<td class="text-xs-right">{{ 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.available}}</td>
</tr>
</template>
</v-data-table>
</template>
Data:
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
available: '',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
available: '',
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
available: '',
},

Use v-select and bind it to item.available on the item slot template...
<template v-slot:item="{ item }">
<tr>
<td>{{item.name}}</td>
<td>{{item.calories}}</td>
<td>{{item.fat}}</td>
<td>{{item.carbs}}</td>
<td>{{item.protein}}</td>
<td>
<v-select
v-model="item.available"
:items="['in stock','unavailable']">
</v-select>
</td>
</tr>
</template>
https://codeply.com/p/9zqiPQEl80

Related

How to expand/collapse column in vue js

I am working with vue.js with vuetify framework, i am trying to show/hide column. How can i do that with vue. In Vuetify documentation , there is only expand/collapse for row like this
enter image description here
export default {
data: () => ({
singleExpand: false,
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
sodium: 87,
calcium: '14%',
iron: '1%',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
sodium: 129,
calcium: '8%',
iron: '1%',
},
],
}),
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<v-container fluid>
<v-switch v-model="singleExpand"
label="Expand Single Item"></v-switch>
<v-data-iterator :items="desserts"
item-key="name"
:items-per-page="4"
:single-expand="singleExpand"
hide-default-footer>
<template v-slot:default="{ items, isExpanded, expand }">
<v-row>
<v-col v-for="item in items"
:key="item.name"
cols="12"
sm="6"
md="4"
lg="3">
<v-card>
<v-card-title>
<h4>{{ item.name }}</h4>
</v-card-title>
<v-switch :input-value="isExpanded(item)"
:label="isExpanded(item) ? 'Expanded' : 'Closed'"
class="pl-4 mt-0"
#change="(v) => expand(item, v)"></v-switch>
<v-divider></v-divider>
<v-list v-if="isExpanded(item)"
dense>
<v-list-item>
<v-list-item-content>Calories:</v-list-item-content>
<v-list-item-content class="align-end">
{{ item.calories }}
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-content>Fat:</v-list-item-content>
<v-list-item-content class="align-end">
{{ item.fat }}
</v-list-item-content>
</v-list-item>
</v-list>
</v-card>
</v-col>
</v-row>
</template>
</v-data-iterator>
</v-container>
</template>
I want to make a dynamic column that can expand/collapse. here is what i expected to do. i really dont know how to make it, can i make it with vuetify or have to do with vue native.
enter image description here

vuejs Editing conditions of data from

I'm making a table listing with vuejs. My data from the database is as above. I'm transferring the data that comes with axios to "data.userList". What I want to do is; if "transaction_type" I want to edit. If I try to convert the data from the table, it will be too long. what should i do for him?
Examle:
I want to make the conditions I have written more regular. Considering that there are thousands of "transaction_types" like this, it's a lot of work. how can i edit this?
"transaction_type" I want to rename it according to the type of incoming data.
const app = new Vue({
el: '#app',
data: {
userList: [{
id: 1,
name: "Prem",
age: 18,
status: "close",
gender: "male",
transaction_type: 'initial_account_balance'
},
{
id: 2,
name: "Chandu",
status: "close",
age: 20,
gender: "female",
transaction_type: 'contact_debit'
},
{
id: 3,
name: "Jong",
status: "open",
age: 21,
gender: "female",
transaction_type: 'contact_credit'
},
{
id: 4,
name: "Steew",
status: "open",
age: 33,
gender: "male",
transaction_type: 'account_debit'
},
{
id: 5,
name: "Abdollah",
status: "open",
age: 26,
gender: "female",
transaction_type: 'account_credit'
},
{
id: 6,
name: "Jerry",
status: "open",
age: 35,
gender: "male",
transaction_type: 'account_debit'
}
]
}
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<script src="https://unpkg.com/vue-router#2.0.0/dist/vue-router.js"></script>
<div id="app">
<table class="table table-hover table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Status</th>
<th>Type</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, i) in userList" class="position-relative">
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
<td>{{ user.status }}</td>
<td>
<p v-if="user.transaction_type ==='initial_account_balance'">Opening Balance</p>
<p v-if="user.transaction_type ==='contact_debit'">Customer Advance</p>
<p v-if="user.transaction_type ==='contact_credit'">Customer</p>
<p v-if="user.transaction_type ==='account_debit'">Customer sales</p>
<p v-if="user.transaction_type ==='account_credit'">Customer Buy</p>
</td>
<td>
{{ user.gender }}
<!-- This can be placed in any of the <td>'s -->
<a class="stretched-link" :href="`#${user.id}`"></a>
</td>
</tr>
</tbody>
</table>
</div>
One idea is to give the user a select based on transaction types found in the data. filter the large data set with the user's selection...
const app = new Vue({
el: '#app',
data: {
xactionType: '',
userList: [{
id: 1,
name: "Prem",
age: 18,
status: "close",
gender: "male",
transaction_type: 'initial_account_balance'
},
{
id: 2,
name: "Chandu",
status: "close",
age: 20,
gender: "female",
transaction_type: 'contact_debit'
},
{
id: 3,
name: "Jong",
status: "open",
age: 21,
gender: "female",
transaction_type: 'contact_credit'
},
{
id: 4,
name: "Steew",
status: "open",
age: 33,
gender: "male",
transaction_type: 'account_debit'
},
{
id: 5,
name: "Abdollah",
status: "open",
age: 26,
gender: "female",
transaction_type: 'account_credit'
},
{
id: 6,
name: "Jerry",
status: "open",
age: 35,
gender: "male",
transaction_type: 'account_debit'
}
]
},
computed: {
xactionTypes() {
return this.userList.map(e => e.transaction_type);
},
filteredData() {
return this.xactionType ? this.userList.filter(e => e.transaction_type === this.xactionType) : this.userList;
}
},
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<script src="https://unpkg.com/vue-router#2.0.0/dist/vue-router.js"></script>
<div id="app">
<div>
<label for="xactionType">Select transaction type:</label>
<select id="xactionType" v-model="xactionType">
<option v-for="(type, i) in xactionTypes" :key="i" :value="type">{{type}}</option>
</select>
</div>
<table class="table table-hover table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Status</th>
<th>Type</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, i) in filteredData" class="position-relative">
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
<td>{{ user.status }}</td>
<td>
<p v-if="user.transaction_type ==='initial_account_balance'">Opening Balance</p>
<p v-if="user.transaction_type ==='contact_debit'">Customer Advance</p>
<p v-if="user.transaction_type ==='contact_credit'">Customer</p>
<p v-if="user.transaction_type ==='account_debit'">Customer sales</p>
<p v-if="user.transaction_type ==='account_credit'">Customer Buy</p>
</td>
<td>
{{ user.gender }}
<!-- This can be placed in any of the <td>'s -->
<a class="stretched-link" :href="`#${user.id}`"></a>
</td>
</tr>
</tbody>
</table>
</div>

place a vuetify slot outside of its component

I am trying to put the headers for a vuetify v1.5 v-data-table component outside of the data table component itself. Does anyone know how to achieve this? The below does not work:
<template>
<div>
<template slot="headers" slot-scope="props">
<th
v-for="header in props.headers"
:key="header.text"
:class="['table-header']">
{{ header.text }}
</th>
</template>
</div>
//some other unrelated code
<v-data-table
:headers="headers"
:items="desserts"
class="elevation-1"
>
<template v-slot:items="props">
<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>
</template>
</v-data-table>
</template>
I don't know if I understand right, let me know in a comment if my unswer is not what you meant.
Proposition: Create one v-data-table with all your headers and data. And above it another v-data-table with just headers.
See how it works in a codepen - v-data-tables
// v-data-table - with items
<v-data-table
:headers="headers"
:items="desserts"
class="elevation-1"
>
<template v-slot:items="props">
<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>
</template>
</v-data-table>
// v-data-table - just headers
<v-data-table
:headers="headers"
:items="desserts"
class="elevation-1"
hide-actions
></v-data-table>
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%'
},
],
},
}

Is it possible to create a multi-line header in a Vuetify datatable?

I would like to create a table with a multiline header, like in this example.
I've found this post, however the answer does not work. Furthermore, I have looked at the Vuetify documentation and Github issues, but there seems to be no solution.
Would be great if someone could let me know whether something like this is possible and if so how.
It turns out you can simply implement your own categories line above the default headers if you just add <thead> in the slot template. Leaving out the <thead> puts it underneath.
<v-data-table ...>
<template v-slot:header="props" >
<thead>
<tr>
<th colspan="2">Category 1</th>
<th colspan="3">Category 2</th>
</tr>
</thead>
</template>
</v-data-table>
You can probably use slot="headerCell". Note that the version of Vuetify used here is 1.5.11
Here's a sample that might give you some pointers:
<v-data-table
v-bind:headers="headers"
v-bind:items="items"
v-bind:search="search"
v-bind:pagination.sync="pagination"
hide-actions
class="elevation-1"
>
<template slot="headerCell" scope="props">
<div slot="activator">
{{ props.header.text }}
</div>
<div>
<span>A</span>
<span>||</span>
<span>B</span>
</div>
</template>
<template slot="items" scope="props">
.....
</template>
</v-data-table>
Here's the codepen link : https://codepen.io/nizantz/pen/KYyLOp
Hope it helps your case.
(Note to moderator who deleted my earlier post: I accidentally posted the answer to a wrong question and I already deleted it.)
This is Core code
<v-data-table :headers="surgeryInformationHeaders" :items="surgeryInformationDesserts" hide-default-footer class="transparent elevation-0 my-4" hide-default-header disable-pagination disable-sort :items-per-page="5">
<template #header="{ }">
<thead class="v-data-table-header">
<tr>
<th v-for="(h,i) in surgeryInformationHeaders" :key="i" class="text-center parent-header td-border-style" :rowspan="h.children?1:2" :colspan="h.children?h.children.length:1">
{{ h.text }}
</th>
</tr>
<tr>
<th v-for="(h1,i1) in getSubHeader(surgeryInformationHeaders)" :key="i1" class="text-center child-header td-border-style">
{{ h1.text }}
</th>
</tr>
</thead>
</template>
<template #item="props">
<tr>
<td v-for="(c,ci) in getRows(props.item)" :key="ci">
{{ c }}
</td>
</tr>
</template>
</v-data-table>
Here's codeopen link https://codepen.io/sunhao1256/pen/MWeZyMe
Here's another sample that might help your case, based on your comment
Note that the data structure needs to be in the right format.(Child elements)
Vue-Template :
<div id="app">
<v-data-table
:headers="headersTop"
:items="tableitems"
hide-actions
>
<template slot="items" scope="props">
<td>
<v-data-table
:headers="[{text:'First Name', value:'fname', sortable:false},
{text:'Last Name', value:'lname', sortable:false}
]"
:items="props.item.name"
hide-actions
>
<template slot="items" scope="props">
<td>{{props.item.fname}}</td>
<td>{{props.item.lname}}</td>
</template>
</v-data-table>
</td>
<td>
<v-data-table
:headers="[{text:'Country', value:'country', sortable:false},
{text:'City', value:'city', sortable:false}
]"
:items="props.item.geo"
hide-actions
>
<template slot="items" scope="props">
<td>{{props.item.country}}</td>
<td>{{props.item.city}}</td>
</template>
</v-data-table>
</td>
</template>
</v-data-table>
</div>
Script:
new Vue({
el: '#app',
data () {
return {
pagination: {},
headersTop:[
{
text: 'Name',
value: 'name',
sortable: false,
},
{
text: 'Geo',
value: 'geo',
sortable: false,
}
],
tableitems:[{
name: [{
fname: 'Dakota',
lname: 'Rice'
},
{
fname: 'Minerva',
lname: 'Hooper'
}],
geo: [{
country: 'Niger',
city: 'Oud-Tunrhout',
},
{
country: 'CuraƧao',
city: 'Sinaai-Waas',
}]
}]
}
}
})
Heres's the codepen link : https://codepen.io/nizantz/pen/rbpNrY

"element-ui" table How to change empty cells as '-'.

var Main = {
data() {
return {
tableData: [{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-02',
name: '',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-04',
name: '',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}]
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
#import url("//unpkg.com/element-ui#2.4.11/lib/theme-chalk/index.css");
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/element-ui#2.4.11/lib/index.js"></script>
<div id="app">
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="Date" width="180">
</el-table-column>
<el-table-column prop="name" label="Name" width="180">
<template slot-scope="scope">
{{scope.row.name || '-'}}
</template>
</el-table-column>
<el-table-column prop="address" label="Address">
</el-table-column>
</el-table>
</template>
</div>
I know If I use 'template' tag I can convert null data as '-'.
now let's suppose that I have more than 100 tables and I don't know which cells can be null. putting 'template' to all el-table-columns will be very hard work and inefficient way.
I want to know is there any way that I can change empty cells as '-' at the same time. help me guys
jsfiddle
Just :
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="Date" width="180">
</el-table-column>
<el-table-column prop="name" label="Name" width="180">
<template slot-scope="scope">
<!-- Replace empty cell by '-' --->
<div class="cell" v-if="scope.row.name !== null">{{ scope.row.answer }}</div>
<div v-else class="cell">-</div>
</template>
</el-table-column>
<el-table-column prop="address" label="Address">
</el-table-column>
</el-table>
I'm sure there are many ways to achieve that. But try this:
computed: {
items() {
let data = this.tableData;
for(let item of data) {
for(let key in item) {
if (!item[key]) {
item[key] = '-';
}
}
}
return data;
}
}
<template>
<el-table :data="items" style="width: 100%">
<! -- the rest of the content -->