how can I embed a v-tree-view component in v-data-table ?
I have tried so many times but without any result .
with no vuetify v-tree-table forexample , here comes the question , how to integrate the v-tree-view with v-data-table ?
You can define a slot to customize any column. So there you can insert your treeview. An example:
<template>
<v-data-table
:headers="headers"
:items="cosas"
>
<template v-slot:[`item.description`]>
<td>
<template>
<v-treeview :items="treeItems"></v-treeview>
</template>
</td>
</template>
</v-data-table>
</template>
<script>
export default {
name: 'MyComponent',
data () {
return {
headers:[
{ text: 'Name', value: 'name'},
{ text: 'Description', value: 'description'},
],
cosas:[
{ name: 'Item1', description: 'description1'},
{ name: 'Item2', description: 'description2'},
],
treeItems: [
{
id: 1,
name: 'Applications :',
children: [
{ id: 2, name: 'Calendar : app' },
{ id: 3, name: 'Chrome : app' },
{ id: 4, name: 'Webstorm : app' },
],
},
{
id: 5,
name: 'Documents :',
children: [
{
id: 6,
name: 'vuetify :',
children: [
{
id: 7,
name: 'src :',
children: [
{ id: 8, name: 'index : ts' },
{ id: 9, name: 'bootstrap : ts' },
],
},
],
},
{
id: 10,
name: 'material2 :',
children: [
{
id: 11,
name: 'src :',
children: [
{ id: 12, name: 'v-btn : ts' },
{ id: 13, name: 'v-card : ts' },
{ id: 14, name: 'v-window : ts' },
],
},
],
},
],
},
{
id: 15,
name: 'Downloads :',
children: [
{ id: 16, name: 'October : pdf' },
{ id: 17, name: 'November : pdf' },
{ id: 18, name: 'Tutorial : html' },
],
},
{
id: 19,
name: 'Videos :',
children: [
{
id: 20,
name: 'Tutorials :',
children: [
{ id: 21, name: 'Basic layouts : mp4' },
{ id: 22, name: 'Advanced techniques : mp4' },
{ id: 23, name: 'All about app : dir' },
],
},
{ id: 24, name: 'Intro : mov' },
{ id: 25, name: 'Conference introduction : avi' },
],
},
],
}
}
}
</script>
Set your filters in the template to insert it only in those cells that you need it.
i try with many libraries but i feel very hard dificult, because i want to use crud in nodes child, i created solucion: i used a table of type expanded and this expended area insert other table for child. you can read in official page about expand table:
https://vuetifyjs.com/en/components/data-tables/#expandable-rows
my code:
<v-data-table
item-key="_id"
:headers="headers"
:items="items"
:single-expand="singleExpand"
:expanded.sync="expanded"
show-expand
height="670"
fixed-header
sort-by="_id"
class="elevation-1 mt-sm-5 mt-md-5 mt-lg-5 mt-xl-5"
>
<template v-slot:expanded-item="{ headers, item }">
<td :colspan="headers.length" style="background-color:#C0D0D0">
<v-card class="mx-auto my-1" max-width="900" outlined>
<v-card-text>
<div>
<span><strong> Delivery {{item.name_driver}}</strong></span>
</div>
<v-divider></v-divider>
<div>
<v-data-table
:headers="headersChild"
:items="item.children"
:items-per-page="5"
class="elevation-1"
>
</v-data-table>
</div>
</v-card-text>
</v-card>
</td>
</template>
</v-data-table>
Related
I have here sample families data which has nested children. My problem is I don't know how many x-for should I write since the nested is dynamic (from Database). Would appreciate any answer.
Here's my sample data in the snippet below:
$families = [
{
id: 1,
name: 'Lupe',
children: [
{
id: 3,
name: 'Bertha',
children: [
{
id: 5,
name: 'Hollywood',
children: [
{
id: 6,
root: 5,
children: [],
},
]
},
],
},
{
id: 9,
name: 'Pinnick',
children: [
{
id: 10,
name: 'Andy',
children: []
},
]
},
]
},
{
id: 2,
name: 'Smitty',
child: [
{
id: 4,
name: 'Vito',
children: []
},
],
}
];
Here is the expected output
Draft implementation:
<tbody>
<template x-for="(family, familyKey) in families">
<template x-for="(parent, parentIndex) in family">
<tr :class="rowClass(scenarioKey, itemIndex)">
<h1 x-text="parent.name"></h1>
</tr>
</template>
</template>
</tbody>
You need a recursive rendering function using x-html directive so make sure that the content is safe, otherwise you can put XSS vulnerabilities in your code. Based on this we can write a recursive list generation function that follows the family graph and renders each level:
<div x-data="familyTree">
<ul>
<template x-for="(level, i) in families">
<li x-html="renderLevel(level, i)"></li>
</template>
</ul>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('familyTree', () => ({
families: [
{
id: 1,
name: 'Lupe',
children: [
{
id: 3,
name: 'Bertha',
children: [
{
id: 5,
name: 'Hollywood',
},
],
},
{
id: 9,
name: 'Pinnick',
children: [
{
id: 10,
name: 'Andy',
children: []
},
]
},
]
},
{
id: 2,
name: 'Smitty',
children: [
{
id: 4,
name: 'Vito',
children: []
},
],
}
],
renderLevel(obj, i) {
let has_children = obj.children && obj.children.length
let html = `<span style="padding-left: 10px;"
x-html="'${has_children ? '> ' : '- '}' + level.name"></span>`;
if (obj.children) {
html += `<ul style="padding-left: 10px; padding-bottom: 10px;">
<template x-for='(level,i) in level.children'>
<li x-html="renderLevel(level,i)"></li>
</template>
</ul>`;
}
return html;
},
}))
})
</script>
Output:
> Lupe
> Bertha
- Hollywood
> Pinnick
- Andy
> Smitty
- Vito
const SHOP_DATA = [
{
title: 'Hats',
items: [
{
id: 1,
name: 'Brown Brim',
imageUrl: 'https://i.ibb.co/ZYW3VTp/brown-brim.png',
price: 25,
},
{
id: 2,
name: 'Blue Beanie',
imageUrl: 'https://i.ibb.co/ypkgK0X/blue-beanie.png',
price: 18,
},
{
id: 3,
name: 'Brown Cowboy',
imageUrl: 'https://i.ibb.co/QdJwgmp/brown-cowboy.png',
price: 35,
},
{
id: 4,
name: 'Grey Brim',
imageUrl: 'https://i.ibb.co/RjBLWxB/grey-brim.png',
price: 25,
},
{
id: 5,
name: 'Green Beanie',
imageUrl: 'https://i.ibb.co/YTjW3vF/green-beanie.png',
price: 18,
},
{
id: 6,
name: 'Palm Tree Cap',
imageUrl: 'https://i.ibb.co/rKBDvJX/palm-tree-cap.png',
price: 14,
},
{
id: 7,
name: 'Red Beanie',
imageUrl: 'https://i.ibb.co/bLB646Z/red-beanie.png',
price: 18,
},
{
id: 8,
name: 'Wolf Cap',
imageUrl: 'https://i.ibb.co/1f2nWMM/wolf-cap.png',
price: 14,
},
{
id: 9,
name: 'Blue Snapback',
imageUrl: 'https://i.ibb.co/X2VJP2W/blue-snapback.png',
price: 16,
},
],
},
{
title: 'Sneakers',
items: [
{
id: 10,
name: 'Adidas NMD',
imageUrl: 'https://i.ibb.co/0s3pdnc/adidas-nmd.png',
price: 220,
},
{
id: 11,
name: 'Adidas Yeezy',
imageUrl: 'https://i.ibb.co/dJbG1cT/yeezy.png',
price: 280,
},
{
id: 12,
name: 'Black Converse',
imageUrl: 'https://i.ibb.co/bPmVXyP/black-converse.png',
price: 110,
},
{
id: 13,
name: 'Nike White AirForce',
imageUrl: 'https://i.ibb.co/1RcFPk0/white-nike-high-tops.png',
price: 160,
},
{
id: 14,
name: 'Nike Red High Tops',
imageUrl: 'https://i.ibb.co/QcvzydB/nikes-red.png',
price: 160,
},
{
id: 15,
name: 'Nike Brown High Tops',
imageUrl: 'https://i.ibb.co/fMTV342/nike-brown.png',
price: 160,
},
{
id: 16,
name: 'Air Jordan Limited',
imageUrl: 'https://i.ibb.co/w4k6Ws9/nike-funky.png',
price: 190,
},
{
id: 17,
name: 'Timberlands',
imageUrl: 'https://i.ibb.co/Mhh6wBg/timberlands.png',
price: 200,
},
],
},
]
export default SHOP_DATA;
const UiUxCategories = () => {
return (
<div>
{
Object.keys(SHOP_DATA).map((key) => {
const products = SHOP_DATA[key];
return (
<CategoryPreview key={key} title={key} products={products} />
)
})
}
</div>
)
}
error- products.filter is no a function in categoryPreview component
const CategoryPreview = ({ title, products }) => {
return (
<div >
<h2>{title}</h2>
<div>
{products
.filter((_, idx) => idx < 4)
.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
</div>
);
}
On the vuetify treeview component the #input event is triggered when the selected array is initialised, I don't want this behaviour, I need the input event to be triggered only when the user manually selects/deselects an item
<v-treeview
selectable
selected-color="red"
:value="selected"
:items="items"
#input="input"
></v-treeview>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
selected: [],
items: [
{
id: 1,
name: 'Applications :',
children: [
{ id: 2, name: 'Calendar : app' },
{ id: 3, name: 'Chrome : app' },
{ id: 4, name: 'Webstorm : app' },
],
},
{
id: 5,
name: 'Documents :',
children: [
{
id: 6,
name: 'vuetify :',
children: [
{
id: 7,
name: 'src :',
children: [
{ id: 8, name: 'index : ts' },
{ id: 9, name: 'bootstrap : ts' },
],
},
],
},
{
id: 10,
name: 'material2 :',
children: [
{
id: 11,
name: 'src :',
children: [
{ id: 12, name: 'v-btn : ts' },
{ id: 13, name: 'v-card : ts' },
{ id: 14, name: 'v-window : ts' },
],
},
],
},
],
},
{
id: 15,
name: 'Downloads :',
children: [
{ id: 16, name: 'October : pdf' },
{ id: 17, name: 'November : pdf' },
{ id: 18, name: 'Tutorial : html' },
],
},
{
id: 19,
name: 'Videos :',
children: [
{
id: 20,
name: 'Tutorials :',
children: [
{ id: 21, name: 'Basic layouts : mp4' },
{ id: 22, name: 'Advanced techniques : mp4' },
{ id: 23, name: 'All about app : dir' },
],
},
{ id: 24, name: 'Intro : mov' },
{ id: 25, name: 'Conference introduction : avi' },
],
},
],
}),
mounted() {
this.selected = [1]
},
methods: {
input() {
alert("input should not be triggered")// I don't want this to be triggered unless the user explicitly selects/deselects an item
}
}
})
Here is a codepen with the problem - https://codepen.io/amaieras/pen/yLPLyvZ?editors=1011
See that the alert is shown even if I don't trigger any selection, can I avoid this from happening?
I am using b-table (Bootstrap-vue) with API Laravel.
This is the vue code:
<TableCli
:items="items"
:fields="fields"
:rows="rows"
:perPage="perPage">
</TableCli>
.
data: function () {
return {
mode: "save",
item: {},
items: [],
paises: [{}],
checked: 1,
page: 1,
perPage: 10,
fields: [
{ key: "id", label: "Código", sortable: true },
{ key: "name", label: "Name", sortable: true },
{ key: "tva", label: "TVA", sortable: true },
{ key: "country_id", label: "Country", sortable: true},
{ key: "cp", label: "CP", sortable: true },
{ key: "city", label: "City", sortable: true },
{ key: "address", label: "Address", sortable: true },
{
key: "status",
label: "Status",
sortable: true,
formatter: (value) => (value ? "Yes" : "No"),
},
{ key: "actions", label: "Actions" }
],
};
Methods:
methods: {
loadCli() {
const url = `${baseApiUrl}/api/cli`;
axios.get(url).then((res) => {
this.items = res.data;
});
},
loadCountrys() {
const url = `${baseApiUrl}/api/country`;
axios.get(url).then(res => {
this.country = res.data
})
},
My table returns the country id, how do I return the country name?
Another question, how do I add an action button in the Actions column?
The button to edit and delete.
I think this snippet answers your questions. The main idea is using slot for b-table.
new Vue({
el: '#app',
data() {
return {
table_fields: [
{
key: "title",
label: "Title"
},
{
key: "user",
label: "User"
},
{
key: "id",
label: "Detail Button"
}
],
page_contents: [
{
id: "title-id-1",
title: "title 1",
user: {
id: "user-id-1",
name: "name 1",
},
}
]
}
},
methods: {
do_sth(id) {
console.log(id)
}
}
})
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.min.js"></script>
<div id="app">
<b-table-lite striped small hover :items="page_contents" :fields="table_fields">
<template #cell(id)="data">
<b-button size="sm" #click='do_sth(data.value)'>Detail Button</b-button>
</template>
<template #cell(user)="data">
<span> {{ data.value.id }} </span>
<span> || </span>
<span> {{ data.value.name }} </span>
</template>
</b-table-lite>
</div>
My goal is to normalize this object:
{
talks: [
{
id: 1755,
speakers: [
{
id: 1487,
name: 'John Doe',
},
],
related_talks: [{
id: 14,
speakers: [{
id: 125,
name: 'Jane Doe',
}],
event: {
id: 181,
name: 'First Annual',
},
}],
event: {
id: 180,
name: 'July Party',
},
},
],
};
into this result:
{
entities: {
events: {
181: {
id: 181,
name: 'First Annual'
},
180: {
id: 180,
name: 'July Party'
}
},
speakers: {
125: {
id: 125,
name: 'Jane Doe'
},
1487: {
id: 1487,
name: 'John Doe'
}
},
talks: {
1755: {
id: 1755,
event: 181,
speakers: [ 1487 ],
related_talks: [ 14 ],
},
14: {
id: 14,
speakers: [ 125 ],
event: 180,
}
},
},
result: {
talks: [ 1755, 14 ],
},
}
If you'll notice, the items in related_talks are treated the same as a talk.
My schemas follow the examples and are set up like this:
const speaker = new schema.Entity('speakers');
const event = new schema.Entity('events');
export const talk = new schema.Entity('talks', {
speakers: [speaker],
event,
});
talk.define({ related_talks: [talk] });
No matter what I try, I can't get the items in related_talks to be added to the result.talks array. It is, however, in the entities object.
What is my schema configuration missing in order to accommodate this?
Unfortunately, if this is your requirement, Normalizr is not for you. Alternatively, if you're looking for a list of "talks" by ID, you can use Object.keys(data.entities.talks)