Vue: Placing Vuetify modal inside component - vue.js

I am trying to make a modal component that can be trigged from outside the component.
I created a ModalComponent.vue file which contains:
<template>
<v-dialog persistent max-width="290">
<template v-slot:activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
Open Dialog
</v-btn>
</template>
<v-card>
<v-card-title class="headline">Use Google's location service?</v-card-title>
<v-card-text>Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green darken-1" text #click="dialog = false">Disagree</v-btn>
<v-btn color="green darken-1" text #click="dialog = false">Agree</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: 'modal-component',
data() {
return {
}
},
}
</script>
In my parent component, I am doing:
<modal-component v-if="this.showDialog"></modal-component>
and triggering showDialog from the parent. All that does though is show the OPEN DIALOG button. I am not sure what I am missing to actually open the modal from the parent.

You should try
<modal-component v-if="showDialog"></modal-component>

Vuetify's <v-dialog> component comes closed by default. You need to start it open. You can do that by passing a value to it.
But you also need to let the parent know if the dialog is open or not, so you need to create a prop for modal-component.
Vue.component('modal-component', {
template: `
<v-dialog max-width="290" :value="value" #input="v => $emit('input', v)">
<v-card>
<v-card-title class="headline">Use Google's location service?</v-card-title>
<v-card-text>Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green darken-1" text #click="$emit('input', false)">Disagree</v-btn>
<v-btn color="green darken-1" text #click="$emit('input', false)">Agree</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
`,
props: ['value']
});
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
showDialog: false,
}
})
<head>
<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#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app>
<v-main class="pa-5">
<modal-component v-model="showDialog"></modal-component>
<v-btn #click="showDialog = true">Show modal</v-btn>
<p>
Modal is {{ showDialog ? 'open' : 'closed' }}
</p>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.js"></script>
</body>

Related

How can i center the logo inside vuetify app bar?

I need the logo inside to be displayed exactly in the middle of the app bar. How can I achieve this result taking into consideration the other elements inside the app bar?
I tried using v-spacer after the v-app-bar-icon, but the result doesn't feel centered at all.
One example of what I am trying to achieve is the official nuxt site app bar (when the display is below md size): https://nuxtjs.org/
<v-app-bar fixed app>
<v-app-bar-nav-icon
aria-label="show-or-hide-navigation-menu"
#click.stop="drawer = !drawer"
/>
<nuxt-link aria-label="home-page" to="/">
<v-img
v-show="searchClosed"
:src="require('~/assets/images/example_Logo.svg')"
max-height="55px"
max-width="110px"
class="mb-1"
contain
></v-img>
</nuxt-link>
<v-spacer v-show="searchClosed"></v-spacer>
<v-btn v-show="searchClosed" aria-label="show-user-menu" icon>
<v-icon>mdi-account-circle</v-icon>
</v-btn>
<transition name="slide-fade">
<nav-search
v-show="!searchClosed"
#search-opened="searchClosed = false"
#search-closed="searchClosed = true"
></nav-search>
</transition>
<v-btn
v-show="searchClosed"
aria-label="show-or-hide-search-input"
icon
#click="searchClosed = false"
>
<v-icon>mdi-magnify</v-icon>
</v-btn>
</v-app-bar>
There are two ways to do this-
1. Try putting the v-spacer before and after the logo image-
new Vue({
el: '#app',
vuetify: new Vuetify(),
})
<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>
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<div>
<v-app-bar
color="deep-purple accent-4"
dense
dark
>
<v-app-bar-nav-icon></v-app-bar-nav-icon>
<v-spacer></v-spacer>
<v-img
src="https://picsum.photos/200/300"
max-height="55px"
max-width="110px"
class="mb-1"
contain
></v-img>
<v-spacer></v-spacer>
<v-btn icon>
<v-icon>mdi-heart</v-icon>
</v-btn>
<v-btn icon>
<v-icon>mdi-magnify</v-icon>
</v-btn>
</v-app-bar>
</div>
</v-app>
</div>
2. Use the grid system-
new Vue({
el: '#app',
vuetify: new Vuetify(),
})
<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>
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<div>
<v-app-bar
color="deep-purple accent-4"
dense
dark
>
<v-row>
<v-col align="start">
<v-app-bar-nav-icon></v-app-bar-nav-icon>
</v-col>
<v-col align="center">
<v-img
src="https://picsum.photos/200/300"
max-height="55px"
max-width="110px"
class="mb-1"
contain
></v-img>
</v-col>
<v-col align="end">
<v-btn icon>
<v-icon>mdi-heart</v-icon>
</v-btn>
<v-btn icon>
<v-icon>mdi-magnify</v-icon>
</v-btn>
</v-col>
</v-row>
</v-app-bar>
</div>
</v-app>
</div>

v-btn (floating action button) positioned absolute top does not overflow from v-card (Vue2, Vuetify)

How can I make this not hidden when it overflows the component? Thank you for your help.
<v-card>
<v-btn #click="dialog = false" fab small absolute top right class="error">
<v-icon>
mdi-close
</v-icon>
</v-btn>
</v-card>
Check your CSS - your card is having overflow: hidden. Remove this CSS rule and it will work as expected.
new Vue({
el: '#app',
template: '#main',
vuetify: new Vuetify(),
})
<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#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<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>
<div id="app"></div>
<template id="main">
<v-app>
<v-main class="pa-8">
<v-row justify="center">
<v-card>
<v-btn #click="dialog = false" fab small absolute top right class="error">
<v-icon>
mdi-close
</v-icon>
</v-btn>
<v-card-text>This is some example text</v-card-text>
</v-card>
</v-row>
</v-main>
</v-app>
</template>
You can override the style using vue's CSS deep selector (>>>). Judging by your code, the overflow style must be coming from the v-dialog class (#click="dialog = false", I take for granted you're trying to close a dialog on the click of that button), so just add this to the vue component :
<style scoped>
>>> .v-dialog {
overflow-y: visible;
}
</style>
The '>>>' makes it so the overflow-y property of the v-dialog class is going to be overriden.

v-tooltip only for append-icon

I continue to deal with Vuetify.
Tell me how you can apply a tooltip only for append-icon in a v-text-field?
Now tooltip does not work for icons at all!
codepen
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-text-field
label="Regular"
v-on="on"
append-icon="event"
style="max-width: 200px"
/>
</template>
<span>Tooltip</span>
</v-tooltip>
No way to solve this (By some API option) - The component renders the icon outside of the text-area (Open GitHub issue/feature if you want).
Anyway if you use a simple <v-icon> component it works fine.
Extra details here:
Wrapping v-icon with v-tooltip inside text-field?
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
url: 'https://stackoverflow.com/'
}
})
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.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-content>
<v-container>
<v-text-field label="Hello world">
<v-tooltip slot="append">
<template v-slot:activator="{ on }">
<v-icon v-on="on" color="primary" dark>
mdi-calendar
</v-icon>
</template>
<span>My Tooltip</span>
</v-tooltip>
</v-text-field>
</v-container>
</v-content>
</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>

Vuejs click modifiers don't work on an element inside of another element with click events

I have a button with a click="buttonMethod()" event inside of a card with a dblclick="cardMethod()" event.
Problem
I need to stop all the button clicks from propagating into the parent (card), but .stop and .prevent modifiers don't work, clicking on the button triggers both methods.
In the demo below, you can even see the clicks propagating from the button into the card (ripples appear)
Using click.stop.prevent on the button doesn't help.
Using dblclick.self on the card doesn't really help either, since it prevents clicks on all children even the text, which is undesirable.
Code
DEMO: https://codepen.io/AlekseiHoffman/pen/LYVKeBE?editors=1011
<v-card #dblclick="cardMethod()" v-ripple>
<div>
<h2>Title</h2>
<h3>Description</h3>
</div>
<v-btn #click.stop.prevent="buttonMethod()">
button
</v-btn>
</v-card>
Solution
I would take the #dblclick event out of the parent v-card and put it only in the area that you want to be clickable.
In this case the div which contains everything beside the button.
<div id="app">
<v-app id="inspire">
<h1>See events in the console</h1>
<v-card v-ripple class="card elevation-8">
<div #dblclick="cardMethod()">
<h2>Title</h2>
<h3>Description</h3>
</div>
<v-btn #click.prevent.stop="buttonMethod()" dark color="blue">
button
</v-btn>
</v-card>
</v-app>
</div>
I have hack rather proper solution:
new Vue({
el: '#app',
vuetify: new Vuetify(),
methods: {
cardMethod () {
console.log('cardMethod')
},
buttonMethod () {
console.log('buttonMethod')
}
}
})
.custom-card .v-card__actions { position: absolute; left: 0; bottom: 0 }
.pb-52 { padding-bottom: 52px !important}
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<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>
<div id="app">
<v-app>
<v-content>
<v-container>
<v-card class="custom-card elevation-8" max-width="344">
<v-card-text #dblclick="cardMethod()" v-ripple class="pb-52">
<h2>Title</h2>
<h3>Description</h3>
</v-card-text>
<v-card-actions>
<v-btn #click="buttonMethod()" dark color="blue">Button</v-btn>
</v-card-actions>
</v-card>
</v-container>
</v-content>
</v-app>
</div>
I found the solution. I just added #dblclick.stop.prevent="" to the button:
<v-card #dblclick="cardMethod()" v-ripple>
<div>
<h2>Title</h2>
<h3>Description</h3>
</div>
<v-btn #dblclick.stop.prevent="" #click.stop.prevent="buttonMethod()">
button
</v-btn>
</v-card>

Show Tooltip icon next to textfield label using Vuetify

I am using vuetify's component tooltip. But I am not sure how to implement it right next to the label.
This is how I have it right now.
<v-tooltip right>
<v-icon slot="activator" dark color="primary">info</v-icon>
<span>Please enter the user information correctly.</span>
</v-tooltip>
<v-text-field label="Information" v-model="dummy.info"> </v-text-field>
I want to tooltip icon right next to the Information Label. Please suggest me how can I achieve that.
Update 1
<v-text-field label="Information" v-model="dummy.info">
<template v-slot:append>
<v-icon slot="activator" dark color="primary">info</v-icon>
<span>Please enter the user information correctly.</span>
</template>
</v-text-field>
Update 2
<v-text-field
v-model="dummy.info"
label='Information'
append-icon="info"
suffix="Please enter the user information correctly."
/>
You can append things to a v-text-field using the append slot.
<v-text-field label="Prepend" prepend-icon="mdi-map-marker" />
https://vuetifyjs.com/en/components/text-fields#api
<v-text-field>
<template v-slot:append>
<v-icon slot="activator" dark color="primary">info</v-icon>
<span>Please enter the user information correctly.</span>
</template>
</v-text-field>
For Vuetify 1.xx
<v-text-field
v-model="dummy.info"
label="Information"
append-icon="info"
suffix="Please enter the user information correctly."
/>
https://v1.vuetifyjs.com/en/components/text-fields#example-prefixes-and-suffixes
https://v1.vuetifyjs.com/en/components/text-fields#example-icon
This snippet should work for you...
new Vue({
el: '#app',
vuetify: new Vuetify(),
})
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&ext=.css" rel="stylesheet" />
<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>
<div id="app">
<v-app>
<v-main>
<v-container>
<v-text-field>
<template v-slot:label>
What about <strong>icon</strong> here?
<v-tooltip bottom>
<template #activator="{ on, attrs }">
<v-icon class="mb-2" small v-on="on" v-bind="attrs" style="vertical-align: middle">
mdi-information
</v-icon>
</template> And here is the information...
</v-tooltip>
</template>
</v-text-field>
</v-container>
</v-main>
</v-app>
</div>