I am creating a simple table with vuetify and it turns out that when adding the v-radio-group component, the elements in the row are not adjusted to the height, so this causes the table to look ugly.
what property could i use to make the cols all fit to the same height.
I have looked in several places, even in the documentation and I do not see anything like it.
component:
<template>
<v-container>
<v-row class="text-center" no-gutters>
<v-col v-for="(item, index) in headers" v-bind:key="index">
<v-card v-if="item" :key="index" class="pa-2" outlined tile>
{{ item.nombre }}
</v-card>
</v-col>
</v-row>
<div v-for="(item, index) in items" v-bind:key="index">
<v-row no-gutters class="text-center"
align="center"
>
<v-col
align-self="center"
>
<v-card class="pa-2" outlined tile>
{{ item.nombre }}
</v-card>
</v-col>
<v-col>
<v-card class="pa-2" outlined tile>
{{ item.cantidad }}
</v-card>
</v-col>
<v-col offset-md="12">
<v-card outlined tile>
<v-radio-group v-model="radioGroup">
<v-radio
v-for="n in 2"
:key="n"
:label="`Radio ${n}`"
:value="n"
></v-radio>
</v-radio-group>
</v-card>
</v-col>
</v-row>
</div>
</v-container>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
optRadio: [
{ nombre: "Bueno", value: 1},
{ nombre: "Malo", value: 2},
],
headers: [
{ nombre: "Descripcion", value: "descripcion" },
{ nombre: "Cantidad", value: "cantidad" },
{ nombre: "estado", value: "state" },
],
items: [
{ nombre: "RADIO", cantidad: 1, state: 1 },
{ nombre: "FRONTAL", cantidad: 10, state: 0 },
{ nombre: "PARLANTES", cantidad: 100, state: 2 },
{ nombre: "ENCENDEDOR", cantidad: 100, state: 2 },
{ nombre: "CENICERO", cantidad: 100, state: 2 },
{ nombre: "TAPETES", cantidad: 100, state: 2 },
],
};
},
};
</script>
Your key here is applying correct flex attributes to your grid system.
First you'd have to instruct your colums to place content vertically, not horizontally: <v-col class="d-flex flex-column"
Then, instruct the cards within to grow in the available vertical height: <v-card class="pa-2 flex-grow-1 d-flex" outlined tile>. To get the content centered within the card, add these two flex helpers to the card as well: align-center justify-center
Documentation HERE
Codepen solution HERE
Related
I am trying to understand what I'm doing wrong in here.
<div class="pageContent container-fluid" **v-show="isHidden"**>
<div class="innerPageContent container-fluid">
<div>
<h2>About</h2>
</div>
<div class="container">
<v-row dense>
<v-col v-for="card in cards" :key="card.title" :cols="card.flex">
<v-card dark outlined>
<v-img :src="card.src" class="white--text align-end" height="200px">
<v-card-title v-text="card.title"></v-card-title>
</v-img>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text color="orange" :to="card.route" **#click="isHidden = !isHidden"**>EXPLORE</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</div>
</div>
</div>
data () {
return {
cards: [
{ title: 'Test', src: '', flex: 6, route: '/about/test' },
{ title: 'Test2', src: '', flex: 6, route: '/about/test2' },
],
**isHidden: true,**
}
},
The "About" div is hidden and, upon clicking on "Explore" button, I see "test2" (my second route), but when I go back, the "About" div is no longer displayed.
Is there something I'm missing ?
I have this snippet:
<div id="app">
<v-app id="inspire">
<v-row justify="center" align="center">
<v-col v-for="col in colors" :key="col" class="shrink" style="min-width: 220px;">
<v-text-field v-model="col" hide-details class="ma-0 pa-0" solo>
<template v-slot:append>
<v-menu v-model="menu" top nudge-bottom="105" nudge-left="16" :close-on-content-click="false">
<template v-slot:activator="{ on }">
<div :style="swatchStyle" v-on="on" />
</template>
<v-card>
<v-card-text class="pa-0">
<v-color-picker v-model="col" flat />
</v-card-text>
</v-card>
</v-menu>
</template>
</v-text-field>
</v-col>
</v-row>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
color: '#1976D2',
colors: [
"#1aaa31",
"#1ccc31",
],
menu: false,
}),
computed: {
swatchStyle() {
const { color, menu } = this
return {
backgroundColor: color,
cursor: 'pointer',
height: '30px',
width: '30px',
borderRadius: menu ? '50%' : '4px',
transition: 'border-radius 200ms ease-in-out'
}
}
}
})
Here is a pen
Each of them (color-pickers) closing right after selecting, I want to prevent this, it's working fine with a single component.
I've already set :close-on-content-click to false, but don't really understand why they opening at once and closing right after click without v-for it works fine.
I am a vuejs newbie and i am having difficulties trying to make my objects return back in a row they are in a column.
components/sellingItems.vue
<template>
<v-container class="my-5">
<v-row>
<v-col
sm="6"
md="4"
>
<v-card outlined>
<v-img :src="image" height="200px" />
<v-card-title> {{ name}} </v-card-title>
<v-card-subtitle> ${{ price }}</v-card-subtitle>
<v-card-actions>
<v-btn #click="addToCart" color="success" outlined >
<v-icon small left> add </v-icon>
Add to Cart
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
props: ['id', 'image', 'name', 'price'],
}
</script>
pages/index.vue
After adding the for loop my products list turns into a column, i prefer it in a row to suit my aim
The Index Page
Stack overflow wont let me post the index page code so heres a screenshot
Check this
use a row and columns by editing your class to determine how many items per row I have added code in codepen
https://codepen.io/Juan-Carlos-MA/pen/yLMdLRX?editors=1010
<div id="app">
<v-app id="inspire">
<br>
<br>
<v-slider
v-model="fruits"
:tick-labels="ticksLabels"
:max="3"
step="1"
ticks="always"
tick-size="4"
></v-slider>
<div class="row">
<div v-for="item in items" :class="selection">
<v-card :loading="loading" class="mx-auto my-12" max-width="374">
<template slot="progress">
<v-progress-linear color="deep-purple" height="10" indeterminate></v-progress-linear>
</template>
<v-img height="250" src="https://cdn.vuetifyjs.com/images/cards/cooking.png"></v-img>
<v-card-title>{{ item.mensaje }}</v-card-title>
<v-divider class="mx-4"></v-divider>
<v-card-title>{{ item.precio }}</v-card-title>
<v-card-actions>
<v-btn color="deep-purple lighten-2" text #click="reserve">
Add TO CART
</v-btn>
</v-card-actions>
</v-card>
</div>
</div>
</v-app>
</div>
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: () => ({
loading: false,
selection: "col-6",
value: 0,
fruits: 1,
ticksLabels: ["one", "two", "tree", "four"],
items: [
{ mensaje: "Tamales", precio: "$300" },
{ mensaje: "Atole", precio: "$300" },
{ mensaje: "Taquito", precio: "$300" },
{ mensaje: "Taquito", precio: "$300" }
]
}),
methods: {
reserve() {
this.loading = true;
setTimeout(() => (this.loading = false), 2000);
}
},
watch: {
fruits: function (val) {
console.log(val);
if (val == 0) {
this.selection = "col-12";
} else {
if (val == 1) {
this.selection = "col-6";
} else {
if (val == 2) {
this.selection = "col-4";
} else {
if (val == 3) {
this.selection = "col-3";
}
}
}
}
}
}
});
Thew problem seems to be that you are creating a new row vor every item
<template>
<v-container class="my-5">
<v-row> <!-- <=== here is your row -->
<v-col sm="6" md="4">
... etc
</v-col>
</v-row>
</v-container>
</template>
you can either move the <v-row> into the parent component and wrap <SellingItems v-for...> or pass an array (products) into the component and have the v-for within that component
<SellingItems :items="products" ... >
<template>
<v-container class="my-5">
<v-row>
<v-col sm="6" md="4" v-for="item in items"> <!-- <=== move v-for here -->
... etc
</v-col>
</v-row>
</v-container>
</template>
In my Vue.js project I have a v-data-table.
If cell content is true I would like to replace with the green check_circle icon.
Why this code isn't working?
<template v-for="header in headers" v-slot:item[header.value]="{ item }">
<v-icon v-if="item[header.value]" color="green">check_circle</v-icon>
</template>
Now the table is:
EDIT 1
<v-data-table
:loading="loading"
:headers="headers"
:items="items"
:items-per-page="items_per_page"
:search="search"
no-data-text="Non ci sono elementi"
no-results-text="Non ci sono elementi filtrati"
loading-text="Caricamento in corso..."
:footer-props="footerProps"
class="elevation-1">
<template v-for="header in headers" v-slot:item[header.value]="{ item }">
<v-icon v-if="item[header.value]" color="green">check_circle</v-icon>
<v-icon v-else color="red">cancel</v-icon>
</template>
<template v-slot:item.actions="{ item }">
<v-icon
small
class="mr-2"
#click="editItem(item)"
>mdi-pencil</v-icon>
<v-icon
small
#click="deleteItem(item)"
>mdi-delete</v-icon>
</template>
<template v-slot:top>
<v-toolbar flat color="white">
<v-spacer></v-spacer>
<v-dialog v-model="dialog" max-width="500px">
<template v-slot:activator="{ on }">
<v-btn color="primary" dark class="mb-2" #click="newItem" v-on="on">New Item</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">{{ formTitle }}</span>
</v-card-title>
<v-card-text>
<v-container>
<!-- modifica elemento -->
<v-row v-if="editedIndex > -1">
<v-col v-for="(key,i) in keys_visible" :key="key" v-show="headers_visible[i].visible == true" cols="12" sm="6" md="4">
<v-text-field v-if="headers_visible[i].type == 'varchar'" v-model="editedItem[key]" :label="headers_visible[i].text" :disabled="!headers_visible[i].editable"></v-text-field>
<v-switch v-else-if="headers_visible[i].type == 'bit'" v-model="editedItem[key]" :label="headers_visible[i].text"></v-switch>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="close">Cancel</v-btn>
<v-btn color="blue darken-1" text #click="save">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:no-data>
<v-btn color="primary" #click="initialize">Reset</v-btn>
</template>
</v-data-table>
headers is like this:
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Actions', value: 'actions', sortable: false },
]
a item is like this:
item: {
cleaned: true,
name: '',
usable: 0,
...
}
To iterate the headers dynamically for all items you'd need to use the body slot...
<template v-slot:body="{ items }">
<tr v-for="idx in items">
<td v-for="header in headers" class="text-left font-weight-black">
<v-icon v-if="idx[header.value]" color="green">check_circle</v-icon>
</td>
</tr>
</template>
Demo: https://codeply.com/p/W0vKEyRGRO
Also see: Vuetify Datatable - Enable content editing on all columns
Problem:
I'm trying to figure out how to pass a value of a clicked item into another component
See codepen: https://codepen.io/anon/pen/zRXBNY
In the codepen menu of an item is triggered by right click
Let's say we have a loop (this iterator component) that's displaying all the items of object items
<v-data-iterator
:items="items"
hide-actions
class="ma-4"
>
<v-flex
slot="item"
slot-scope="props"
xs12 sm6 md4 lg3
>
<v-card #contextmenu="show" class="ma-3 elevation-4">
<v-card-title>
<h4>{{ props.item.name }}</h4>
</v-card-title>
</v-card>
</v-flex>
</v-data-iterator>
And we also have this "menu" component in the same .vue component:
<v-menu
absolute
offset-y
:position-x="x"
:position-y="y"
v-model="showMenu"
>
<v-list>
<p class="white ma-3">menu for item: [TITLE]</p>
<v-list-tile
v-for="item in menuItems"
:key="item.title" #click=""
>
<v-list-tile-title>
{{ item.title }}
</v-list-tile-title>
</v-list-tile>
<v-text-field
class="ma-3"
label="rename">
</v-text-field>
</v-list>
</v-menu>
Question:
How do we trigger the menu component and pass the data of that particular item in it (so that we can do something with it)? As an example I put this menu for item: [TITLE] paragraph there, I don't understand how do we pass the title of the clicked item there?
It seem a bit messy to me (i'm not very familiar with Vuetify), but the first solution that comes to my mind is to pass item object to the handler. So your code goes as:
<v-card #contextmenu="show($event, props.item)" class="ma-3 elevation-4"></v-card>
Then once the event is fired and handler function is called you can store the item you clicked on:
show (e, item) {
this.selectedItem = item;
e.preventDefault()
// ...
Now you can use the item inside the model component as:
<v-list>
<p class="white ma-3">
menu for item: {{selectedItem.name}}
</p>
//...
Full demo:
new Vue({
el: '#app',
methods: {
show (e, item) {
this.selectedItem = item;
e.preventDefault()
this.showMenu = false
this.x = e.clientX
this.y = e.clientY
this.$nextTick(() => {
this.showMenu = true
})
}
},
data: () => ({
x: 0,
y: 0,
selectedItem: {},
showMenu: false,
menuItems: [
{ title: 'copy' },
{ title: 'paste' },
{ title: 'delete' }
],
items: [
{
value: false,
name: 'Frozen Yogurt'
},
{
value: false,
name: 'Ice cream sandwich'
},
{
value: false,
name: 'Eclair'
},
{
value: false,
name: 'Cupcake'
}
]
})
})
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify/dist/vuetify.min.js"></script>
<div id="app" >
<v-app id="inner" class="grey lighten-3">
<h1 class="ma-2 ml-4">right click on an item to trigger menu</h1>
<!-- ITEMS ON THE PAGE -->
<v-data-iterator
:items="items"
hide-actions
class="ma-4"
>
<v-flex
slot="item"
slot-scope="props"
xs12 sm6 md4 lg3
>
<v-card #contextmenu="show($event, props.item)" class="ma-3 elevation-4">
<v-card-title>
<h4>{{ props.item.name }}</h4>
</v-card-title>
</v-card>
</v-flex>
</v-data-iterator>
<!-- MENU COMPONENT -->
<v-menu
absolute
offset-y
:position-x="x"
:position-y="y"
v-model="showMenu"
>
<v-list>
<p class="white ma-3">menu for item: {{selectedItem.name}}</p>
<v-list-tile
v-for="item in menuItems"
:key="item.title" #click=""
>
<v-list-tile-title>
{{ item.title }}
</v-list-tile-title>
</v-list-tile>
<v-text-field
class="ma-3"
label="rename">
</v-text-field>
</v-list>
</v-menu>
</v-app>
</div>