Vuejs - Handle key press and Click on table row - vue.js

How I can capture key press and click on a tr element ?
I need to implement a table that can handle a single row selection, or multiple-row selection.
Right now, I tried to bind the key ctrl:
Vue.directive('on').keyCodes.ctrl = 17;
But, if i use #keyup.ctrl sure this dont works, because I need to check what key is pressed when the user click on a row.

The click event includes properties that indicate whether Control, Shift, Alt, or Meta keys were pressed during the click.
new Vue({
el: 'body',
data: {
controlled: false,
shifted: false,
meta: false,
alted: false
},
methods: {
clicked: function(event) {
console.debug(event);
this.controlled = event.ctrlKey;
this.shifted = event.shiftKey;
this.meta = event.metaKey;
this.alted = event.altKey;
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<button #click="clicked">Click me!</button>
<div v-if="controlled">Control was pressed</div>
<div v-if="shifted">Shift was pressed</div>
<div v-if="alted">Alt was pressed</div>
<div v-if="meta">Meta was pressed</div>

Related

In VueJs, how to get event #focusout of a complete radio button group

I have built my custom radio button group component, and it mostly works fine. However, I want to emit a "group focusout" event, when the focus leaves outside of any of the contained radio buttons.
However, the #focusout of the buttons all fire individually, and I can not find a way to determine whether the target is outside the group.
Component code
I am basically doing (simplified):
<div v-for="(obj, index) in items" :key="index">
<label :for="id + '-' + obj.value">
<input
:name="name ? name : id"
:key="index"
:id="id + '-' + obj.value"
:value="obj.value"
:checked="obj.selected"
#focusout="onFocusout"
#change="updateRadiobuttons($event.target.value)"
/>
{{ $t(obj.text) }}
</label>
</div>
In the #focusout handler I do some validation (not shown) and simply pass the event:
private onFocusout(value) {
console.debug('onFocusout', value);
//...validation...
this.$emit('focusout', value);
}
Events emitted
I am logging the received events and watch the log (with Chrome F12)
Here's what I get when I just change the option inside the radio group:
FocusEvent {isTrusted: true, relatedTarget: input#caseBestaDataSearchResultSchule-3.form-control, view: Window, detail: 0, sourceCapabilities: null, …}
bubbles: true
cancelBubble: false
cancelable: false
composed: true
currentTarget: null
defaultPrevented: false
detail: 0
eventPhase: 0
isTrusted: true
path: (20) [input#caseBestaDataSearchResultSchule-2.form-control, label, div.radio.radio--left, div.radio-inline, div.col-sm-9, div.form-group, div.form-group, fieldset, form.form-horizontal, span, div, div, div#content.col-sm-12, div.row, div.container-fluid, div.container.container-main, body.mod.mod-layout.skin-layout-template-contentpage, html, document, Window]
relatedTarget: input#caseBestaDataSearchResultSchule-3.form-control
returnValue: true
sourceCapabilities: null
srcElement: input#caseBestaDataSearchResultSchule-2.form-control
target: input#caseBestaDataSearchResultSchule-2.form-control
timeStamp: 46397.884999983944
type: "focusout"
view: Window {window: Window, self: Window, document: document, name: "", location: Location, …}
which: 0
__proto__: FocusEvent
Here's what I get when I click into the surrounding space:
FocusEvent {isTrusted: true, relatedTarget: null, view: Window, detail: 0, sourceCapabilities: InputDeviceCapabilities, …}
bubbles: true
cancelBubble: false
cancelable: false
composed: true
currentTarget: null
defaultPrevented: false
detail: 0
eventPhase: 0
isTrusted: true
path: (20) [input#caseBestaDataSearchResultSchule-3.form-control, label, div.radio.radio--left, div.radio-inline, div.col-sm-9, div.form-group, div.form-group, fieldset, form.form-horizontal, span, div, div, div#content.col-sm-12, div.row, div.container-fluid, div.container.container-main, body.mod.mod-layout.skin-layout-template-contentpage, html, document, Window]
relatedTarget: null
returnValue: true
sourceCapabilities: InputDeviceCapabilities {firesTouchEvents: false}
srcElement: input#caseBestaDataSearchResultSchule-3.form-control
target: input#caseBestaDataSearchResultSchule-3.form-control
timeStamp: 54147.71499999915
type: "focusout"
view: Window {window: Window, self: Window, document: document, name: "", location: Location, …}
which: 0
__proto__: FocusEvent
How to get a single event #focusout of the whole group?
I'm assuming that you currently fire the focus event when cycling through each radio using up & down arrows, or selecting another option via touch.
If that is the case the only way you can truly know the focus status of the other radio buttons is to look at them, using ref's to compare each element to document.activeElement or storing each radios focus state.
You could also check the class names if you have any focus classes active.
Heres an example of using the data object to store focus state.
Also worth mentioning you need to use nextTick here or the data object won't have updated before you read the data object.
new Vue({
el: '#app',
data() {
return {
maleFocused: false,
femaleFocused: false,
otherFocused: false
}
},
methods: {
focusIn(e) {
this[`${e.srcElement.id}Focused`] = true
},
async focusOut(e) {
this[`${e.srcElement.id}Focused`] = false
await this.$nextTick()
const radioMaleFocused = this.maleFocused
const radioFemaleFocused = this.femaleFocused
const radioOtherFocused = this.otherFocused
const radiosFocused = radioMaleFocused || radioFemaleFocused || radioOtherFocused
if (!radiosFocused) {
console.log('run your code here!')
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<fieldset>
<legend>Radios</legend>
<input type="radio" id="male" name="gender" value="male" #focusin="focusIn" #focusout="focusOut">
<label for="male">Male</label><br>
<input type="radio" id="female" name="gender" value="female" #focusin="focusIn" #focusout="focusOut">
<label for="female">Female</label><br>
<input type="radio" id="other" name="gender" value="other" #focusin="focusIn"#focusout="focusOut">
<label for="other">Other</label>
</fieldset>
</div>

How to execute a function when Click Button (X) on Input Field search vuejs

I need to do an action when Click Button (X) on search is clicked using Vue.
when he clicks on the input seach? on "x
new Vue({
el: "#app",
data: {
msg: 'the input is cleaned',
info:''
},
methods: {
handleClick: function(){
// to do sonthing when is cleaned not before
if(this.info=='')
alert(this.msg)
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="search" v-model="info" #click="handleClick" >
<br>
<span>{{ info }}</span>
</div>
You seem to want to differentiate between a normal click inside a input[type="search"] and a click on its clear control. I've spent some time trying to compare the two clicks and I wasn't able to find how they differ.
But I came up with a trick to figure it out:
if the input has a value (you need one for the clear button to be displayed)
we wait for DOM to update and, after it did, if the input no longer has a value (it was cleared) => bingo! it was a clear search click.
Therefore:
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
methods: {
handleClick(e) {
if (e.target.value) {
this.$nextTick() // wait for DOM update
.then(() => {
if (e.target.value === '') {
console.log('clear button clicked you must have, young Jedi!');
}
})
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="search" #click="handleClick">
</div>
However, I believe you're better off with a watch on your v-model:
watch: {
info(newVal, oldVal) {
if (oldVal && !newVal) {
console.log('info was cleared').
}
}
}
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data: () => ({ info: '' }),
watch: {
info(newVal, oldVal) {
if (oldVal && !newVal) {
console.log('morning has broken...');
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="search" v-model="info">
</div>
It has the advantage it will not only trigger on click. It will trigger every time info changes from a truthy value to a falsy one, regardless of what caused the change (i.e: user selecting the text and pressing Delete or Backspace; any other component method clearing it, resetting the input or the parent form, etc...).
From the comment on the question, you're asking to call a function when the user clicks on the input field ? It's the way that I understood your question.
For that case, here is a quick demo on how to achieve that.
https://codesandbox.io/s/dry-lake-34bvi?file=/src/App.vue

Toggle Other Elements in VueJS

I am creating a navbar in VueJS where I toggle on or off drop-down menus. I have no problem toggling an individual drop-down menu, but I cannot figure out how to handle multiple-drop down menus so that if I open up one menu the other ones will automatically close.
For instance, let's take a look at the following code:
// template
<button #click="isMenuOneOpen = !isMenuOneOpen">Menu One<button>
<button #click="isMenuTwoOpen = !isMenuTwoOpen">Menu Two<button>
<button #click="isMenuThreeOpen = !isMenuThreeOpen">Menu Three<button>
<button #click="isMenuFourOpen = !isMenuFourOpen">Menu Four<button>
...
// script --> data
isMenuOneOpen: false,
isMenuTwoOpen: false,
isMenuThreeOpen: false,
isMenuFourOpen: false,
Let's say I click on menu one and then click on menu two (and then three and four). With my current code, all four menus will be open. What I want, though, is that if I click on a particular menu, not only will it open up but the other drop-down menus will close.
How can I do this using VueJS?
Thanks.
Here's a sample code. But the problem here is that, once you disable the button, you won't be able to click it. Maybe add a checkbox to enable all buttons?
Here's the html:
<div id="app">
<v-app id="inspire">
<div v-for="button in buttons">
<button #click="updateMenu(button.name)" :disabled='button.isDisabled'>{{ button.name }}</button>
</div>
</v-app>
</div>
Here's the javascript:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
buttons: [{name: "menu one", isDisabled: false}, {name: "menu two", isDisabled: false}, {name: "menu three", isDisabled: false}, {name: "menu four", isDisabled: false}]
}),
methods: {
updateMenu: function (name) {
const button = this.buttons.find(b => b.name === name);
button.isDisabled = false;
const toDisableButtons = this.buttons.filter(b => b.name != name);
toDisableButtons.forEach(function(item) {
item.isDisabled = true;
});
}
}
});

How to use keyboard buttons to manipulate numbers

How to click a button not only directly clicking mouse, but pressing a button on a keyboard (in this case, its a keyboard button with a value "1" that hasevent.key` = 1)???
new Vue({
el: "#app",
data: {
one: 1
},
methods: {
add(){
this.one++;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button v-on:1 #click="add">One</button>
<span> {{ one }}</span>
</div>
If you want to listen for global keyboard events you'll need to add the listener to the window, otherwise you need focus on element that the event is dispatched from.
It's just plain vanila js from there:
new Vue({
el: "#app",
data: {
one: 1
},
created() {
const component = this;
this.handler = function (e) {
e.keyCode == 38 && component.add()
e.keyCode == 40 && component.remove()
}
window.addEventListener('keyup', this.handler);
},
beforeDestroy() {
window.removeEventListener('keyup', this.handler);
},
methods: {
remove() {
this.one--;
},
add(){
this.one++;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="add">One</button>
<span> {{ one }}</span>
</div>
This is covered in the VueJS documentation.
From the documentation:
Key Modifiers
When listening for keyboard events, we often need to check for
specific keys. Vue allows adding key modifiers for v-on when listening
for key events:
<!-- only call `vm.submit()` when the `key` is `Enter` --> <input
v-on:keyup.enter="submit">
You can directly use any valid key names exposed via KeyboardEvent.key
as modifiers by converting them to kebab-case.
<input v-on:keyup.page-down="onPageDown">
In the above example, the handler will only be called if $event.key is
equal to 'PageDown'.

Toggle text on mouse hover

I have some text:
Hover me
on positioning the cursor over the text, I would like it to change to:
I'm being hovered
on moving the cursor off, the text should change back to:
Hover me
I can do this with CSS, but I can't figure out how to do it with Vue?
Something like this should work.. easiest if you use a computed property.
CodePen mirror: https://codepen.io/oze4/pen/XQapNP
new Vue({
el: "#app",
data: {
hover: false
},
computed: {
message() {
return this.hover === true ? "I'm being hovered" : "Hover me";
}
},
methods: {
handleHover(s){
this.hover = s;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="app">
<p #mouseover="handleHover(true)" #mouseleave="handleHover(false)">
{{ message }}
</p>
</div>
You need to define the output you want and a boolean for the hover state, I've called it "hoover"
data: () => ({
hoover: false
}),
computed: {
tyext() {
if (this.hoover === false) {
return "Hover Me"
}
return "I'm being hovered"
}
}
Then in the template you can have event listeners to change the boolean.
<p #mouseenter="hoover = true" #mouseleave="hoover = false">{{ tyext }}</p>
You typically wouldn't have logic like this in your template and would instead call a function like this #mouseenter="changeHoover" and change the state but I showed this for brevity, which was kind of pointless as I keep banging on like this.