Passing in prop in scoped-slot not working - javascript

I am trying to wrap my table inside of a slot for reusability purposes but I am having trouble with passing in my label prop:
My main parent component Parent.vue:
<Table
:headers="headers"
:items="people"
:search="search"
:label="label"
>
<template scope="props">
Label is: {{ label }} <!-- this label is not printing out -->
<v-data-table :headers="props.headers" :items="people" :search="props.search">
<template slot="items" slot-scope="props">
<td>{{ props.item.firstName }}</td>
<td>{{ props.item.lastName }}</td>
<td>{{ props.item.email }}</td>
</template>
</v-data-table>
</template>
</Table>
My Table component:
<template>
<div>
<slot :items="items" :headers="headers" :search="search" scoped-slot="{label: label}"></slot>
</div>
</template>
<script>
export default {
data() {
return {
label: "Some label"
}
},
computed: {
},
props: ["items", "headers", "search"]
}
</script>
This method gives me error Property or method "label" is not defined. Could someone help point out where I am going wrong with passing in the label prop?

You need to access it as props.label instead of just label
<template slot-scope="slotProps">
Label is: {{ slotProps.label }} <!-- this label is not printing out -->
<v-data-table :headers="props.headers" :items="people" :search="props.search">
<template slot="items" slot-scope="props">
<td>{{ props.item.firstName }}</td>
<td>{{ props.item.lastName }}</td>
<td>{{ props.item.email }}</td>
</template>
</v-data-table>
</template>
and in Table component, passing label as simple as other binding value:
<template>
<div>
<slot :items="items" :headers="headers" :search="search" :label="label"></slot>
</div>
</template>

Related

Vuetify v-data-table add complex data

i am working on v-data-table. I couldn't figure out how to process the information from the backend. Could you help?
i tried this code but i get vue.runtime.esm.js:1897 TypeError: this.items.slice is not a function
<v-data-table :headers="headers" :items="products" class="elevation-1" :search="search">
<template slot="item" slot-scope="props">
<tr>
<td>{{ props.item.id }}</td>
<td class="text-xs-right">{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.id }}</td>
<td class="text-xs-right">{{ props.item.category}}</td>
....
<v-btn icon class="mx-0" #click="editItem(props.item)">
<v-icon class="mx-0 primary--text white--text">edit</v-icon>
</v-btn>
<v-btn icon class="mx-0" #click="deleteItem(props.item)">
<v-icon class="mx-0 red--text white--text">delete</v-icon>
</v-btn>
</td>
</tr>
</template>
data from api
{
"items": [
{
"name":"test",
"id":1,
"category":"test"
}
],
}
The data you receive from the API is stored in the items array
data(){
return {
items: []
If that is the case then you will need to do this:
v-data-table :items="items"
and not products like you have above.
Docs

Clicking on row in v-data-table with template rows

When I added template rows (so that they have special formatting based on condition):
<v-data-table
:headers="headers"
:items="desserts"
:items-per-page="5"
class="elevation-1"
#click:row="clickedHandle"
>
<template v-slot:item="props">
<tr v-if="props.item.name.includes('Fro')">
<td>{{ props.item.name }}</td>
<td v-for="itemx in myheaders">{{ toThousands(props.item[itemx]) }}</td>
</tr>
<tr v-else>
<td v-for="itemx in props.item">{{ itemx }}</td>
</tr>
</template>
</v-data-table>
The function that is supposed to be called on row click clickedHandle does not fire up at all. Why is that so?
Here is the example where you can check this behaviour:
https://codesandbox.io/s/vuetify-playground-forked-lro4w?file=/src/layout.vue
The table does not seem to react on row click at all.
clickedHandle(value) {
console.log(value);
},
clickedHandle should log some value on row click.
Customize each cell individually as they do in the v-data-table row customization docs, not the whole row. You can use a v-for to dynamically target the cell slots you want (in conjunction with your myheaders array):
<template v-for="header in myheaders" v-slot:[`item.${header}`]="props">
<template v-if="props.item.name.includes('Fro')">
{{ toThousands(props.item[header]) }}
</template>
<template v-else>
{{ props.item[header] }}
</template>
</template>
You could avoid this slot and filter complexity by preparing your data ahead of time in a computed.
Here is an updated CodeSandbox
try with this code:
<v-data-table
:headers="headers"
:items="desserts"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="myprops">
<tr v-if="myprops.item.name.includes('Fro')">
...
</tr>
<tr v-else>
<td v-for="itemx in props.item">{{ itemx }}</td>
</tr>
</template>
</v-data-table>

Vue - button is not visible inside v-data-table

I have a problem with v-data-table. I want to add button for edit, delete and add new product to my v-data-table. Data comes from my rest api and is assign via my getter CARS to v-data-table. Everything is fine and every single row is displayed but button is not shown.... I tried a lot of different approaches but it still doesn't work..
I would be grateful if You help me.
Best regards!
Here is my code.
<v-data-table
v-model="selected"
:headers="headers"
:items=CARS
:single-select="singleSelect"
item-key="id"
show-select class="elevation-1"
>
<template slot="items" slot-scope="props">
<td>{{ props.item.id }}</td>
<td>{{ props.item.vin }}</td>
<td>{{ props.item.register_number}}</td>
<td>{{ props.item.cost}}</td>
<td>{{ props.item.latitude }}</td>
<td>{{ props.item.longitude}}</td>
<td>{{ props.item.service}}</td>
<td>{{ props.item.reservation}}</td>
<td class="justify-content-left layout">
<v-btn icon #click.prevent="editUser(props.item)">
<v-icon color="blue">edit</v-icon>
</v-btn>
</td>
</template>
</v-data-table>

How to show and hide rows in v-data-table Vue.js + Vuetify

I'm new at Vue developer and I make a V-Data-Table consuming a JSON with vue-resource. That´s done already, but now I want to show/hide child rows based on user selection.
e.g.: click on '+' and the table shows the rows, click on '-'and the table hide the rows.
<template>
<v-app>
<div>
<v-flex xs12 sm6 d-flex>
<v-select
v-if="retornoDoJson"
:items="retornoDoJson.nations"
v-model="paisSelecionado"
label="Selecione Um"
v-on:change="selectionChanged"
single-line
menu-props="bottom"
></v-select>
</v-flex>
</div>
<div v-if="paisSelecionado">
<v-data-table :headers="headers" :items="retornoDoJson.top_10s[paisSelecionado]" hide-actions>
<template slot="items" slot-scope="props">
<v-btn fab dark color="indigo">
<v-icon dark>add</v-icon>
</v-btn>
<td class="parent-row">{{ props.item.name }}</td>
<td class="child-row">{{ props.item.club }}</td>
<td class="child-row">{{ props.item.phy }}</td>
<td class="parent-row">{{ props.item.age }}</td>
<td class="parent-row">{{ props.item.pas }}</td>
<td class="child-row">{{ props.item.nationality }}</td>
</template>
</v-data-table>
</div>
</v-app>
</template>
<script>
export default {
data() {
return {
paisSelecionado:undefined,
headers: [
{
text: ' ',
align: 'left',
sortable: false,
value: 'name'
},
{ text: 'name', value: 'name' },
{ text: 'club', value: 'club' },
{ text: 'phy', value: 'phy' },
{ text: 'age', value: 'age' },
{ text: 'pas', value: 'pas' },
{ text: 'nationality', value: 'nationality' }
],
retornoDoJson: []
};
},
methods: {
loadApi() {
this.$http
.get("http://localhost:8080/data.json")
.then(this.successCallback, this.errorCallback);
},
successCallback: function(resposta) {
this.retornoDoJson = resposta.data;
console.log(this.retornoDoJson);
},
selectionChanged: function() {
console.log("selecionarItem:this.selecionarPais:", this.paisSelecionado);
}
},
mounted() {
this.loadApi();
}
};
</script>
<style>
</style>
There's any way to do that?
If I understood you correctly, I hope this helps, also you can check a working example here: https://codepen.io/anon/pen/zemZoB
<template slot="items" scope="props">
<template v-if="props.item.show">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">
<v-btn #click.native="props.item.show = false">
Hide
</v-btn>
</td>
</template>
<template v-else>
<v-btn #click.native="props.item.show = true">
Show
</v-btn>
</template>
</template>

How to make content in an expand slot of a data table in VuetifyJS searchable?

I'm using the VuetifyJS/VueJS data table with an expand slot. How to make the content in the expand slot searchable? I tried wrap the content within <td></td> but that didn't work.
Here is a codepen example: https://codepen.io/anon/pen/VBemRK?&editors=101
If you search for "find me" it always results in a Your search for "find me" found no results.
<v-data-table
:headers="headers"
:items="desserts"
:search="search"
item-key="name"
>
<template slot="items" slot-scope="props">
<tr #click="props.expanded = !props.expanded">
<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>
<template slot="expand" slot-scope="props">
<v-card flat>
<v-card-text><td>Peek-a-boo! Please find me too.</td></v-card-text>
</v-card>
</template>
<v-alert slot="no-results" :value="true" color="error" icon="warning">
Your search for "{{ search }}" found no results.
</v-alert>
</v-data-table>
Use a custom filter.
First, create a custom filter method:
methods: {
customFilter(items, search) {
return items.filter(dessert => JSON.stringify(dessert).toLowerCase().indexOf(search.toLowerCase()) !== -1)
}
}
then add :custom-filter="customFilter" to the v-data-table:
<v-data-table
:headers="headers"
:custom-filter="customFilter"
:items="desserts"
:search="search"
item-key="name"
>
See this updated codepen:
https://codepen.io/WisdomSky/pen/PBNvYY
Since Vuetify version >= 2 you'll need to use the custom-filter prop which has a new pattern.
export default {
methods: {
customDataTableItemsFilter(value, search, items) {
/*
Filter for individual words in search string. Filters
all object values rather than just the keys included
in the data table headers.
*/
const wordArray = search
.toString()
.toLowerCase()
.split(' ')
.filter(x => x)
return wordArray.every(word =>
JSON.stringify(Object.values(items))
.toString()
.toLowerCase()
.includes(word)
)
}
}
}

Categories

Resources