Vue multiple color-pickers on one page - vue.js

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.

Related

v-data-table change color selected row

I would like to change the background color of the selected row in a v-data-table.
<v-data-table dense :headers="headers"
:items="records"
#click:row="handleClick"> <!-- handleClick is a function that logs item for the moment... -->
<template v-slot:[`item.index`]="{item}">
<v-row justify="center">
<v-col>
<div>{{item.index}}</div>
</v-col>
</v-row>
</template>
<template v-slot:[`item.status`]="{ item }">
<v-row justify="center">
<v-col v-if="item.status===1">
<v-icon color="green">
mdi-check-circle
</v-icon>
</v-col>
<v-col v-else>
<v-icon color="orange">
mdi-progress-check
</v-icon>
</v-col>
</v-row>
</template>
</v-data-table>
I couldn't find a way to distinguish the selected row from the others and thus update the style for the selected one.
Basically i'd like to reproduce the behavior implemented for the v-list component.
Selected rows have the v-data-table__selected class applied on their TR tag - so you can just create some CSS override to target them. The default style in Vuetify is
.theme--light.v-data-table tbody tr.v-data-table__selected
{
background: #f5f5f5;
}
You can use item-key="index" and single-select to select row and set class tr.v-data-table__selected:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
headers: [{text: 'index', value: 'index'}, {text: 'status', value: 'status'}],
records: [{index: 1, status: 1}, {index: 2, status: 0}, {index: 3, status: 1}],
selected: null
}
},
methods: {
handleClick(item, row) {
row.select(true);
this.selected = item
}
}
})
tr.v-data-table__selected {
background: lime !important;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
<div>{{ selected }}</div>
<v-data-table dense :headers="headers"
:items="records" item-key="index" single-select
#click:row="handleClick">
<template v-slot:[`item.index`]="{item}">
<v-row justify="center">
<v-col>
<div>{{item.index}}</div>
</v-col>
</v-row>
</template>
<template v-slot:[`item.status`]="{ item }">
<v-row justify="center">
<v-col v-if="item.status===1">
<v-icon color="green">
mdi-check-circle
</v-icon>
</v-col>
<v-col v-else>
<v-icon color="orange">
mdi-progress-check
</v-icon>
</v-col>
</v-row>
</template>
</v-data-table>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>

Conditional Rendering in VueJS

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 ?

Keep v-menu open state when the activator is pressed again

I'm trying to make a custom v-autocomplete using v-text-field and v-menu.
What confuses me is that v-menu closes when you click on the v-text-field again. The first click on the v-text field opens the v-menu, and the second click closes it. I couldn't find any property that turns off toggle mode.
Although, if you look at the html markup, v-menu is used in the v-select and v-autocomplete components, which close when you click on the content or outside the menu.
Codepen
<template>
<div id="app">
<v-app id="inspire">
<div class="text-center">
<v-main>
<v-container>
<v-row>
<v-col cols="3">
<v-menu bottom offset-y max-height="304px">
<template v-slot:activator="{ on, attrs }">
<v-text-field v-model="model && model.title"
dense color="primary"
v-bind="attrs" v-on="on"
label="Choose" outlined>
</v-text-field>
</template>
<v-list dense>
<v-list-item-group v-model="model"
color="primary">
<v-list-item v-for="(item, index) in items"
:key="item.id" :value="item"
dense>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list-item-group>
</v-list>
</v-menu>
</v-col>
</v-row>
</v-container>
</v-main>
</div>
</v-app>
</div>
</template>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: [
{id:1, title: 'Click Me 1' },
{id:2, title: 'Click Me 2' },
{id:3, title: 'Click Me 3' },
{id:4, title: 'Click Me 4' },
],
model: null
}),
})
</script>

how can i call objects in a row using vuetify?

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>

How to get values of an item in the loop in Vue?

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>