Check if v-dialog is open and stop audio playing - vue.js

I would like have a watcher on the v-dialog to stop audio files playing when the dialog is open. Usually I would have v-model="dialogVisible" and then add a watch. But as I have multiple dialogs I have had to use a v-model="media.show" for the dialog.
this.audioPlayer.pause()
this.isPlaying = false
How can I now check for when the dialog is open and then set the above to prevent audio files playing while a dialog is open?
<v-list-item-action>
<div v-if="media.url.includes('mp3')">
<v-btn
v-if="isPlaying && (currentMedia.id === media.id)"
icon
#click="pause"
>
<v-icon>pause</v-icon>
</v-btn>
<v-btn
v-else
icon
#click="play(media)"
>
<v-icon>play_arrow</v-icon>
</v-btn>
</div>
<div v-else>
<v-dialog
v-model="media.show"
persistent
width="800px"
:retain-focus="false"
>
<template v-slot:activator="{ on, attrs }">
<v-btn
icon
v-bind="attrs"
v-on="on"
>
<v-icon>mdi-open-in-new</v-icon>
</v-btn>
</template>
<v-card>
<Video
v-if="media.show"
:video-url="media.url"
/>
</v-card>
<v-card-actions>
<v-spacer />
<v-btn
color="primary"
text
#click="media.show = false"
>
Close
</v-btn>
</v-card-actions>
</v-dialog>
</div>
</v-list-item-action>

What you can do is watch for a specific prop change. In your case media.show. When it changes this triggers your dialog to show. So when you are watching that prop to change you can trigger a function that you can do anything with. In this case we will pause the music when the value becomes true and resume it becomes false.
watch: {
media: {
deep: true,
handler(newVal) {
//Modal is displayed
if (newval.show) {
this.audioPlayer.pause()
this.isPlaying = false
} else {
//Resume when modal is closed (optional(
this.audioPlayer.play();
this.isPlaying = false;
}
}
}
}

Related

Instance of v-dialog is generated twice – Vuetify

I have a problem with <v-dialog> that appears everywhere in my Vue.js application using Vuetify.js.
Every <v-dialog> is loading twice on the page. You can see it by looking at how it appears:
If I close one dialog the other dialog stays visible and works exactly like the first. It seems like Vue is generating two instances of it.
The code of the dialog isn't the issue, I think:
<v-dialog
v-model="dialog"
persistent
hide-overlay
no-click-animation
>
<v-card>
<v-card-title>Text</v-card-title>
<v-card-text>
<p class="subtitle-1">Some more text</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
depressed
>
Next
<v-icon right>mdi-chevron-right</v-icon>
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
The v-model is declared in data():
export default {
data() {
return {
dialog: true,
};
},
}
Any help is appreciated! Thanks.

how I can change the background color by clicking button using vuetify?

Here, I have used vuetify to create buttons which pop up dialog box that contains buttons with different colors and I want to use buttons to change the background color of navigation and menu bar but due to my limited knowledge on vue and vuetify I am not able to change my background color. Can anyone help me???
My code is here:
<template>
<v-row justify="center">
<v-dialog v-model="dialog" persistent max-width="600px" class="pa-md-4 mx-lg-auto">
<template v-slot:activator="{ on }">
<v-btn color="primary" dark v-on="on">Theme</v-btn>
</template>
<div class="text-center">
<v-btn v-for="(item) in colors" :color="item" dark large class="ma-2" style="width:100px;">
<span class="text-truncate" style="width:120px;">
{{item.replace(/-/g, '')}}
</span>
</v-btn>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="dialog = false">Close</v-btn>
<v-btn color="blue darken-1" text #click="dialog = false">Save</v-btn>
</v-card-actions>
</div>
</v-dialog>
</v-row>
</template>
<script>
export default {
data(){
return{
colors: ["red","pink","purple","deep-purple","indigo","blue","light-blue","cyan","teal","green","light-green","lime","yellow","amber","orange","deep-orange","brown","blue-grey","grey", "black"],
dialog: false
}
},
} </script>
To do this you actually use themes that you setup in vuetify.js and you can assign different colors to the different values for example primary: '#c3c3c3' and define different themes within your app. It comes with light and dark theme but you can also add/remove themes programmatically.
It's quite a bit of code so I will post the links on where directions can be found here.
https://vuetifyjs.com/en/customization/theme/#custom-theme-variants
And the actual usage can be found here:
https://vuetifyjs.com/en/customization/theme/#usage

Delete line in Vuetify data-table with delete button in dialog

I have data-table with an edit and delete icon to each line. When using the code below and pressing the delete icon I get a system pop-up and the the line deletes the way I want it. So perfect.
<template v-slot:item.actions="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">mdi-pencil</v-icon>
<v-icon small text #click="deleteItem(item)">mdi-delete</v-icon>
</template>
Methods script:
deleteItem(item) {
const index = this.companies.indexOf(item);
confirm("Are you sure you want to delete this item?") &&
this.companies.splice(index, 1);
},
Now instead of the system pop-up I want to have a nice dialog. Like in https://codepen.io/anon/pen/pYzZPZ?editors=1010.
So I've made this code:
<template v-slot:item.actions="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">mdi-pencil</v-icon>
<v-icon small #click="dialog2 = true">mdi-delete</v-icon>
<v-dialog v-model="dialog2" max-width="500px">
<v-card>
<v-card-title>Verwijderen</v-card-title>
<v-card-text>Weet je zeker dat je {{item.name}} wenst te verwijderen?</v-card-text>
<v-card-actions>
<v-btn color="primary" text #click="dialog2 = false">Close</v-btn>
<v-btn color="primary" text #click="deleteItem(item)">Verwijderen</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
And with Methods script:
deleteItem(item) {
const index = this.companies.indexOf(item);
this.companies.splice(index, 1);
this.dialog2 = false;
console.log("Delete success");
},
I've added the console log to see if the button actually did something.
When I press the delete icon now I do get the dialoge. When I press "close" everything is fine.
When I press delete I get the message "Delete success" in console but the line is not deleting.
When I press the delete button again the page crashes....Any ideas?
The problem is that there are multiple instances of v-dialog bound to dialog2 because it's inside a slot that repeats. This is different than the single instance of window.confirm that works. So, when you attempt to deleteItem(item) the item to delete is always the last in the array.
Put the v-dialog dialog outside the v-data-table, and keep track of the itemToDelete (this same way edit works). Use a method to toggle the dialog and remember the item...
showDeleteDialog(item) {
this.itemToDelete = item
this.dialogDelete = !this.dialogDelete
},
deleteItem() {
console.log('deleteItem', this.itemToDelete)
const index = this.items.indexOf(this.itemToDelete)
this.items.splice(index, 1)
this.dialogDelete = false
},
Then the template is...
<v-data-table>
<template v-slot:item.actions="{ item }">
<div class="text-truncate">
<v-icon
small
class="mr-2"
#click="editItem(item)"
>
mdi-pencil
</v-icon>
<v-icon
small
#click="showDeleteDialog(item)"
>
mdi-delete
</v-icon>
</div>
</template>
</v-data-table>
<v-dialog v-model="dialogDelete" max-width="500px">
<v-card>
<v-card-title>Delete</v-card-title>
<v-card-text>Weet je zeker dat je `{{itemToDelete.Name}}` wenst te verwijderen?</v-card-text>
<v-card-actions>
<v-btn color="primary" text #click="dialogDelete = false">Close</v-btn>
<v-btn color="primary" text #click="deleteItem()">Delete</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
Demo

How to avoid mutating a prop directly when all you have is a click?

How can I mutate a prop the correct way, so that I don't get the [Vue warn]: Avoid mutating a prop directly message?
I already got the v-model to work on this v-dialog. However, I also want to provide a close button in the dialog itself, which causes this mutation warning, as it's the dialog itself that's mutating the variable. How best to approach this case and solve it?
Dialog.vue:
<template>
<v-dialog
:value="value" #input="$emit('input', $event)"
scrollable
width="80vw"
:transition="false"
>
<template v-slot:activator="{ on }">
<div v-on="on" #click="$emit('open')">
<slot name="button">
<v-btn color="primary">{{ buttonText == null ? title : buttonText }}</v-btn>
</slot>
</div>
</template>
<v-card
elevation="10"
height="80vh"
>
<v-system-bar
color="light-blue darken-3"
window
>
<span>{{title}}</span>
<v-spacer></v-spacer>
<v-icon #click="value=false">mdi-close</v-icon>
</v-system-bar>
<v-card-text> <!-- required here to make the scrollable v-dialog work -->
<slot></slot>
</v-card-text>
<slot name="actions"></slot>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: {
title: {
type: String,
required: true,
},
buttonText: String,
value: Boolean,
},
}
</script>
I can use it quite nicely like:
<mydialog title="Select something" button-text="A button!" v-model="dialog" #open="loadData()">
Content goes here...
</mydialog>
The <v-icon #click="value=false">mdi-close</v-icon> is what's incorrectly mutating the "value"-variable.
Sidenote #1: The open event is there so I can populate data (loadData) from a database when the dialog is opened (vs. when its created on the DOM).
UPDATE; I can get it to work by doing:
<v-icon #click="$emit('close', $event)">mdi-close</v-icon>
and
<mydialog title="Select something" button-text="A button!" v-model="dialog" #open="loadData()" #close="dialog=false">
However, I feel this is far from being elegant. Aren't there any solutions in where I don't need to add on-Handlers to close this dialog? I almost feel that this is worse than living with the warning.. :|
Use a computed property with get and set. The dialog computed will behave exactly as a normal variable and it will eliminate the warning. Now you can use it to get the value and also to set the value.
Try this:
<template>
<v-dialog
:value="dialog"
#input="$emit('input', $event)"
scrollable
width="80vw"
:transition="false"
>
<template v-slot:activator="{ on }">
<div v-on="on" #click="dialogOpened()">
<slot name="button">
<v-btn color="primary">{{ buttonText == null ? title : buttonText }}</v-btn>
</slot>
</div>
</template>
<v-card elevation="10" height="80vh">
<v-system-bar color="light-blue darken-3" window>
<span>{{title}}</span>
<v-spacer></v-spacer>
<v-icon #click="dialog=false">mdi-close</v-icon>
</v-system-bar>
<v-card-text>
<!-- required here to make the scrollable v-dialog work -->
<slot></slot>
</v-card-text>
<slot name="actions"></slot>
</v-card>
</v-dialog>
</template>
export default {
props: ['title', 'buttonText', 'value'],
data: () => ({
dlg_close: false,
}),
computed: {
dialog: {
get() {
return this.value;
},
set(selection) {
this.$emit("input", selection);
}
}
},
methods: {
dialogOpened(newVal) {
this.dialog = newVal;
},
},
}

Reset Vuetify form validation

I have trouble resetting vuetify validation in v-dialog.
This codepen is the simplified version of what I have.
https://codepen.io/yuukive/pen/BVqpEZ
With the code above, if I do
(Open dialog --> press SAVE button --> (validation fails) --> press CLOSE button --> open dialog again),
it is already validated when I open the dialog again...
Is it possible to reset validation before a user opens it the 2nd time?
new Vue({
el: '#app',
data: () => ({
dialog: false,
emailRules: [v => !!v || 'Name is required']
}),
methods: {
onSave() {
if (!this.$refs.form.validate()) return
dialog = false
}
}
})
<div id="app">
<v-app id="inspire">
<v-layout row justify-center>
<v-dialog v-model="dialog" persistent max-width="500px">
<v-btn slot="activator" color="primary" dark>Open Dialog</v-btn>
<v-card>
<v-card-title>
<span class="headline">Email</span>
</v-card-title>
<v-form ref="form">
<v-card-text>
<v-container grid-list-md>
<v-layout wrap>
<v-flex xs12>
<v-text-field label="Email" required :rules="emailRules"></v-text-field>
</v-flex>
</v-layout>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" flat #click.native="dialog = false">Close</v-btn>
<v-btn color="blue darken-1" flat #click.native="onSave">Save</v-btn>
</v-card-actions>
</v-form>
</v-card>
</v-dialog>
</v-layout>
</v-app>
</div>
Example from docs uses:
this.$refs.form.reset()
Note that while reset() clears validation, it clears input as well.
You can follow this issue to see further updates on this.
So you can perhaps watch dialog value and reset the form:
watch: {
dialog() {
this.$refs.form.reset()
}
}
resetValidation() will clear validation errors only, reset() will also clear input fields.
this.$refs.form.reset() might work on JavaScript, but compiler for TypeScript complains about typing. Even though during serve you can only see errors in the terminal without breaking the app, it'll actually break when you'll try to build the app.
Creating a new variable and assigning into it any type does the trick, below an example:
const refForm: any = this.$refs.form;
refForm.reset();