V-tooltip: Close Popover from a method - vue.js

In VueJS, I'm using v-tooltip (https://github.com/Akryum/v-tooltip) for popovers.
In order to close a popup, they provide a directive called 'v-close-popover' which I can assign to a button/link inside the popover to close the popup. This works well.
However, I have a requirement where I need to close this popup from a Vue method. But I dn't know how to trigger closing of the popover from the method.

This is how you can achieve this.It will display tooltip on mouseOver event and remove on mouseLeave event.
In template->
<i
id="requiredIcon"
aria-hidden="true"
v-tooltip="{content: 'Required option is not available for this question.', show: isOpen, trigger: 'manual'}"
#mouseover="showTooltip"
#mouseleave="removeTooltip"
></i>
In Script->
data() {
return {
isOpen: false,
};
},
methods:{
showTooltip() {
this.isOpen = true;
},
removeTooltip() {
this.isOpen = false;
}
}

In case anybody else stumbles upon this issue, the v-popover component has a hide method. So if you were to place a ref on your popover component then you can access the hide method from it and call it :)

Related

Bootstrap Vue - Prevent dropdown close on click outside

I'm using Bootstrap-Vue and I would like my dropdown to never hide until a button calls a function. My issue is that, by default, clicking outside the dropdown or on the dropdown button hide the dropdown. My template is:
<b-dropdown
ref="dropdown"
#hide="onEditControlMenuHide"
#click.native.stop>
<b-dropdown-form>
<b-dropdown-item-button
#click="closeDropdown"
>I'm a button
</b-dropdown-item-button>
</b-dropdown-form>
</b-dropdown>
And then I have simple methods in my script:
closeDropdown() {
this.$refs.dropdown.hide()
},
onEditControlMenuHide(bvEvent) {
bvEvent.preventDefault()
},
I tried to catch the bvEvent in a function to process where the event comes from, but I find nothing in the event that differentiate hide on click outside, hide on click the dropdown button, or hide because on my custom button.
I read that it was maybe because of event bubbling, so I tried to use #click.native.stop but it doesn't work. Any help would be appreciated!
You could set a flag that is only set to true by the button's click-handler, then the hide-handler would only cancel the hide if the flag is set:
export default {
methods: {
closeDropdown() {
this._okToHide = true
this.$refs.dropdown.hide()
},
onEditControlMenuHide(bvEvent) {
if (this._okToHide) {
this._okToHide = false
} else {
bvEvent.preventDefault()
}
},
}
})
demo
<b-dropdown-item-button
#click.stop="closeDropdown"
>I'm a button
</b-dropdown-item-button>
try to use .stop modificator with click event on ur button and not on dropdown, it stops propagination event from button and should not trigger click event on dropdown.

Vue #keydown on v-dialog/v-overlay stops working when a <v-card> is present

It seems that the Vue #keydown on v-dialog/v-overlay stops working when a < v-card > is present. Why does this not work, and how to fix?
<v-overlay :value="olyThing" #keydown.esc="olyThing=false" tabindex="0">
<v-card
width="80vw"
height="80vh"
#click="olyThing=false">
</v-card>
</v-overlay>
While this does does work:
<v-overlay :value="olyThing" #keydown.esc="olyThing=false" tabindex="0">
</v-overlay>
Somehow the v-card is preventing the keydown to come through. Tried to put the #keydown on the v-card, but this doesn't fix it. Same effect on a v-dialog, instead on a v-overlay. I also tried doing a #keydown.native.esc, but nothing seems to work.
I'm not looking for a solution involving an eventHandler on the window. I'd like to keep this localized to the component.
I have not been able to figure out why the v-card prevents the #keydown to function. But an alternate solution that still is only active on the current page and not global is this:
A complete setup requires three parts.
The method to call when a key is pressed.
Adding the event listener.
Removing the event listener.
You will need the separate method in order to destroy the event listener later:
methods: {
onKeydown(e) {
if (this.isOverlay) {
if (e.keyCode == 37) {
console.log('LEFT')
} else if (e.keyCode == 39) {
console.log('RIGHT')
}
}
},
}
mounted() {
// Keypresses on overlay:
document.addEventListener('keydown', this.onKeydown)
},
beforeDestroy() {
document.removeEventListener('keydown',this.onKeydown)
},
Thanks to Watermelon Sugar for the suggestion.
Try this approach:
mounted() {
document.addEventListener("keydown", (e) => {
// If ESC key was pressed
if (e.keyCode == 27) {
this.showdialog=false
// or if you have created a dialog as a custom component, emit an event
// this.$emit('closeDialog')
}
});
},

Run method when Vuetify dialog is opened

I have a v-data-table and the user can click on any row and a dialog opens. Inside on my vuetify dialog is a dropdown of data.
I want to filter this data everytime the user clicks on a row and filter out what the user clicked from the dropdown inside the dialog.
Here is my dialog:
<v-dialog v-model="edit" max-width="1200" #input="closeDialog()">
<editCompany :isEdit="true"
v-if="showEdit"
:company="selected"
:adminEdit="true"></editCompany>
</v-dialog>
You can see I'm passing in the values from the table row the user clicked.
Now, I need to use the value being passed in to filter the dropdown. The mounted event only runs once, so my logic inside of it only fires for the first row clicked.
Here is the mounted event inside of my editCompany template:
mounted: async function () {
this.filterOutResults(); //this is where i do my filtering and it works
},
Every other row the user clicks doesn't fire mounted, so I cant use that unless I can unmount the dialog when its closed.
I found how to fire an event when the dialog closes, but I cannot find a vuetify open event.
How do I run a function everytime the dialog opens so I can filter the results or how do I unmount the dialog everytime it closes, so the mounted event can run everytime? Thanks
For future references, I'll expand #mynd comment, which should be the answer:
export default {
data() {
return {
dialogVisible: false,
},
},
watch: {
dialogVisible(visible) {
if (visible) {
// Here you would put something to happen when dialog opens up
console.log("Dialog was opened!")
} else {
console.log("Dialog was closed!")
}
}
},
<v-dialog v-model="dialogVisible" max-width="1200" #input="closeDialog()">
<!-- Add code here, according to Vuetify docs -->
</v-dialog>
For further information (about constructing the v-dialog component itself), refer to the official docs
if you want to do something inside the dialog component when it's open, there is a little workaround that you can do.
<v-dialog v-model="edit" max-width="1200" #input="closeDialog()">
<editCompany :isEdit="true"
v-if="showEdit"
:company="selected"
:dialogOpen="edit"
:adminEdit="true"></editCompany>
</v-dialog>
as you see you can pass dialog's handler variable as dialog's parameter. its 'dialogOpen' in this case.
then inside editCompany component,
watch: {
'dialogOpen' :{
handler(newVal, oldVal) {
//do your stuff.
},
deep: true
},
}
So in short it will watch the variable which is controlling dialog, based on its value which mostly is true or false, you can do your operation.

Close dialog when ESC key is pressed

How can i close a vuetify's dialog opened without an activator, when the user press the ESC key on the keyboard?
Add #keydown.esc="dialog = false" to v-dialog component
<v-dialog v-model="dialog" #keydown.esc="dialog = false"></v-dialog>
data: () => ({
dialog: false
}),
Working example:
https://codepen.io/anon/pen/BJOOOQ
Additionally, if using dialog as custom component then possibly we need to emit input event:
<template>
<v-dialog :value="value" #keydown.esc="$emit('input')">
...
This is the only way I was able to get it to work
mounted() {
// Close modal with 'esc' key
document.addEventListener("keydown", (e) => {
if (e.keyCode == 27) {
this.$emit('close');
}
});
},
this code maybe can help you
mounted() {
let self = this;
window.addEventListener('keyup', function(event) {
// If ESC key was pressed...
if (event.keyCode === 27) {
// try close your dialog
self.advanced_search = false;
}
});
},
the same principle as adding keypress binding to any vue component should work - add the following code to the v-dialog component :
#keydown.esc="dialog = false"
working example ( note the close button click event handler as well )
https://codepen.io/yordangeorgiev/pen/WBeMGq
While the solutions others have mentioned work, there still are conflicts with the bounce animation, making it not work after playing it by clicking outside the dialog, etc.
Setting the no-click-animation property also fixes the animation when closing as otherwise it plays both the close and bounce animation:
<v-dialog v-model="dialog" #keydown.esc="dialog=false" no-click-animation></v-dialog>
#keydown.esc not working with my project. As far as I see it's good for Vue2 projects.
Working script:
mounted() {
document.addEventListener("keydown", (e) => {
if (e.key === 'Escape') {
this.$emit('close');
// Or any other way you want to close your modal
}
})
}
What you want to use is a Key Modifier. You can use v-on:keyup.esc directive on your dialog to detect if the escape key is detected.
Read this for more information about Key Modifiers

Open a modal and fetch data from server on click of a button outside the component

I am very new to Vue.js. In fact I just started today.
I have a problem.
Let's say I have button in a table somewhere in dom.
<table>
<tr><td><button v-on:click="showModal">Show</button>
</table>
Now I have a modal box outside of the scope of the button.
This button is inside a component of itself and the modal box has a component of itself too.
I am passing in an id with this button, and what I want to do is:
Fetch the id on button click
Show the record fetched in the modal and then finally perform some action on it
My problem is I am unable to get a method in the Modal component (that does a http request and fetches and renders the data) to trigger by the click event of this button.
The button and the modal has no relationship, they are not parent/child.
In modal component trigger method to fetch data by component ready state:
ready: function() {
this.getAllTheDataYouNeed();
},
You may use another life cycle hook:
https://vuejs.org/guide/instance.html#Lifecycle-Diagram
An option was to add the event broadcast in the common ancestor of both the components.
Like this:
var main = new Vue({
el: 'body',
components: {
zmodal : zmodal,
showhidebtn : showhidebtn,
},
methods: {
showModal: function (currentId) {
this.$broadcast('openModalBox', currentId);
}
}
});
Add an event listener in 'zmodal' and call this function showModal from on click event of 'showhidebtn' component.
It is working but now I have a set of codes outside the components that have to be triggered for this to work.
I wonder if there is a better way to do this.