How to use keyboard buttons to manipulate numbers - vue.js

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'.

Related

Mass chain handler in Vue2

I have a component (Vue2) with several buttons. After processing every button's #click, I need to call a method.
How can I do it without adding a call into each #click? Of course, all #clicks are different.
The only idea I see is to create component for the button, maybe there are better solutions?
Just use single handler for all #click events and pass the handler function for the specific button as an argument....
new Vue({
el: "#app",
methods: {
handleClick: function(handler) {
handler()
console.log("Common code executed")
},
button1: function() {
console.log("Button 1 clicked")
},
button2: function() {
console.log("Button 2 clicked")
},
button3: function(a) {
console.log(`Button 3 clicked (with additional argument: "${a}")`)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<div id="app">
<button type="button" #click="handleClick(button1)">Button 1</button>
<button type="button" #click="handleClick(button2)">Button 2</button>
<button type="button" #click="handleClick(() => button3('hi!'))">Button 3 (with additional argument)</button>
</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

v-on:click problem if the elements has another element inside

I am dealing with the problem of my click event in vue js. I made a click even on element that has another element inside it.
Here's my code:
<span class="pull-down-controller" #click="pullDown($event)">
<span class="indicator">-</span> Controller
</span>
in the frontend it will show - Controller
if I click the word Controller it will call the specified function which is pullDown() but why is it whenever I click the indicator or the minus symbol, it will not do anything even if it is inside the <span> where I put the #click event?
The reason why I put a <span> inside it so I can change the symbol to + using jquery.
thanks!
No need for jQuery, Vue's reactivity provides all you need:
new Vue({
el: '#app',
template: `
<span #click="pullDown" style="font-size: 48px;">
<span>{{ indicator }}</span> Controller
</span>
`,
data () {
return {
expanded: false
}
},
computed: {
indicator () {
return this.expanded ? '+' : '-'
}
},
methods: {
pullDown (event) {
this.expanded = !this.expanded
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

Vue.js Checkbox issue in Firefox, works file in Chrome and IE

I am using a checkbox.
<template v-for="(item,index) in items">
<div >
<input type="checkbox"
v-model="item.checked"
#click="selectionCheckboxClicked(index,item.checked)"
/>
</div>
.....
And this is the JS code
selectionCheckboxClicked: function selectionCheckboxClicked(index,checked) {
console.log(this.items[index].checked);
console.log(checked);
....
},
Initial value of item.checked is false. When I click the checkbox in Chrome or IE, it checks the checkbox and displays 'true' in console log. However, when I run the code in Firefox, though it does change the state, console log displays false in selectionCheckboxClicked(). I need to take some action based on the current state of the checkbox in selectionCheckboxClicked(), which I ma finding difficult to implement in the current situation.
Shall appreciate any suggestions to fix the issue.
Because for checkbox, v-model bind #change not #input (check Vue Github: source codes for v-model). Then #change will be fired after lose focus.
But you should not rely on the order either #click or #change will be executed first (check this answer for more details).
So one solution is uses #change=handler($event) instead, because v-model uses addHandler with one parameter named important=true to make sure it will be fired first than your event handler.
new Vue({
el: '#app',
data() {
return {
testValues: false
}
},
methods: {
selectionCheckboxClicked: function(ev) {
console.log(this.testValues);
console.log(ev.target.checked);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div>
<input type="checkbox" v-model="testValues" #change="selectionCheckboxClicked($event)" />
</div>
</div>
Or another solution is uses #input but you should rely on what is checked or not on the input Dom element.
new Vue({
el: '#app',
data() {
return {
testValues: false
}
},
methods: {
selectionCheckboxClicked: function(ev) {
console.log('v-model:', this.testValues);
console.log('inputCheckedAtDom:', ev.target.checked);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div>
<input type="checkbox" v-model="testValues" #input="selectionCheckboxClicked($event)" />
</div>
</div>
If you still like to use #click, one solution actually is same as #input. Uses one ref to access the input Dom element.
new Vue({
el: '#app',
data() {
return {
testValues: false
}
},
methods: {
selectionCheckboxClicked: function(ev) {
console.log('v-model:', this.testValues);
console.log('inputCheckedAtDom:', this.$refs.test.checked);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div>
<input ref="test" type="checkbox" v-model="testValues" #click="selectionCheckboxClicked($event)" />
</div>
</div>
setTimeout will work because it will be executed after current task finished and re-render. Even you uses setTimeout(()=>{}, 0)(delay 0 seconds), it will still work.
What seems to be happening is that Firefox calls the click function immediately even before the v-model = "item.checked" has changes. When I check the value of this.items[index].checked after some delay (say 100 ms), it displays true.
console.log(this.items[index].checked);
console.log(checked);
var self = this;
setTimeout(function()
{ if (self.items[index].checked)
self.selectedContactsCount++;
else
self.selectedContactsCount--;
},
100);

Programmatically bind custom events for dynamic components in VueJS

In my vuejs app I use dynamic component in the following way:
<mycomponent>
<component ref="compRef" :is="myComponent" v-bind="myComponentProps"></component>
<div class="my-buttons">
<my-button label="Reset" #click="reset()"/>
</div>
</mycomponent >
myComponent is a prop on the parent component which hold the actual component to inject.
myComponentProps are also prop which holds the porps for the injected instance.
I would like to know how can I also dynamically bind listeners to the component - I have understand that I cannot send an object to v-on with multiple events.
I was thinking about adding it programatically however haven't found any info about how it can be done for Vue custom events (kind for addEventListener equivalent for custom events)
Any tip would be much appreciated!
With Vue 2.2+, you can programmatically add an event listener with $on(eventName, callback):
new Vue({
el: '#app',
created() {
const EVENTS = [
{name: 'my-event1', callback: () => console.log('event1')},
{name: 'my-event2', callback: () => console.log('event2')},
{name: 'my-event3', callback: () => console.log('event3')}
]
for (let e of EVENTS) {
this.$on(e.name, e.callback); // Add event listeners
}
// You can also bind multiple events to one callback
this.$on(['click', 'keyup'], e => { console.log('event', e) })
}
})
<script src="https://unpkg.com/vue#2.6.8/dist/vue.min.js"></script>
<div id="app">
<div>
<!-- v-on:EVENTNAME adds a listener for the event -->
<button v-on:click="$emit('my-event1')">Raise event1</button>
<button v-on:click="$emit('my-event2')">Raise event2</button>
<button v-on:click="$emit('my-event3')">Raise event3</button>
</div>
<div>
<!-- v-on shorthand: #EVENTNAME -->
<button #click="$emit('my-event1')">Raise event1</button>
<button #click="$emit('my-event2')">Raise event2</button>
<button #click="$emit('my-event3')">Raise event3</button>
</div>
</div>
With Vue 2.6+, you can add an event listener dynamically in the template:
new Vue({
el: '#app',
data: {
eventname: 'click',
},
methods: {
handler(e) {
console.log('click', e.target.innerText)
}
}
})
<script src="https://unpkg.com/vue#2.6.8/dist/vue.min.js"></script>
<div id="app">
<button #[eventname]="handler">Raise dynamic event</button>
<!-- Set dynamic key to null to remove event listener -->
<button #click="eventname = null">Unbind event</button>
</div>
You can also declaratively bind multiple event listeners with v-on="{event1: callback, event2: callback, ...}":
new Vue({
el: '#app',
methods: {
onClick() { console.log('click') },
onKeyUp(e) { console.log('keyup', e.keyCode) }
}
})
<script src="https://unpkg.com/vue#2.6.8/dist/vue.min.js"></script>
<div id="app">
<input type="text" placeholder="type here" v-on="{click: onClick, keyup: onKeyUp}">
</div>