Lagging in v-on:change - vue.js

I had an input with v-on:change directive in it to call some method I declared inside the Vue objects. But I realized there are delays in calling the method whenever the value is changed.
I reproduced it in here:
HTML
<div id="demo">
<input type="number" min=0 v-on:change="change">
<p>{{num}}</p>
</div>
Javascript
var data = {
num:0
}
var demo = new Vue({
el: '#demo',
data: data,
methods: {
change: function(event) {
console.log(event.target.value);
this.num = event.target.value;
}
}
})
https://jsfiddle.net/lookman/4y2wmxot/2/

There is no delay actually, unless you click outside the input field in result section, on-change will not be triggered. It is triggered when focus changes from the input field, as you have only one element this is triggered when you click manually in the result section.
If you just add one more component, like I did here, and now you enter some value and press tab, you will see change immediately, you can do this in your fiddle also, enter value and press tab (which will remove focus)
If you want to trigger on each change
You can use input event instead of change event to trigger the method for each change.
The DOM input event is fired synchronously when the value of an or element is changed.
Code changes:
<input type="number" min=0 v-on:input="change">
Update fiddle: https://jsfiddle.net/4y2wmxot/4/

For this use case, you really should be using v-model anyways:
<div id="demo">
<input type="number" min=0 v-model="num">
<p>{{num}}</p>
</div>
Then there's no need for the method at all:
var data = {
num:0
}
var demo = new Vue({
el: '#demo',
data: data,
})

try keyup instead change:
<input type="number" min=0 v-on:change="change">
https://jsfiddle.net/lookman/4y2wmxot/2/
will you face any limitation to prevent you to use another kind of event?

Related

Vue - Click handler in repeated div will not force update by itself, need to do it manually

When I have a click handler in a div that is repeated with v-for, it seems like changes made in that click handler will not be updated in the DOM.
Why?
https://jsfiddle.net/AndersBillLinden/109uzsx7/27/
html:
<div id="vue">
<input type="checkbox" v-model="force_update"/> force update
<div v-for="e in arr">
{{e.id}} = {{e.text}}
click
<span v-show="e.clicked"> clicked</span>
</div>
</div>
js:
new window.Vue(
{
el: '#vue',
data:
{
arr: [{id:1,text:"one"}, {id:2, text:"two"}, {id:3, text:"three"}],
force_update: true
},
methods:
{
on_link_clicked(e)
{
e.clicked = true;
if (this.force_update)
this.$forceUpdate();
}
}
});
clicking link 1
unchecking force update
clicking the 2nd link
(nothing happens)
checking "force update"
Now the changes in the previous step are rendered.
The conclusion is that we sometimes needs to force the update, but it is unclear why.
Change e.clicked = true; to this.$set(e, 'clicked', true) so it adds reactivity to the property which is not already in the model.

Vue v-on:click change it to load or mouse over event

I am trying to get v-bind:value on to function reservationBy() as load event instead of v_on:clickevent. Right now it passes the value when I click on it only.
Is there a way to make it load automatically or use mouse over event? I even try to use v-on:load and v-on:focus event but it did not work.
View
<div id="app">
<input v-bind:value="2" v-on:click="reservationBy"/>
</div>
Script
new Vue({
el: "#app",
data: {
},
methods: {
reservationBy: function(e) {
var peopleBookedId = e.target.value;
console.log(peopleBookedId);
}
}
})
Here is example on JSFIDDLE
https://jsfiddle.net/ujjumaki/yz0p1vqL/4/
#mouseover and #mouseleave will do the job.
<input v-bind:value="2" #mouseover="reservationBy"/>
or
<input v-bind:value="2" #mouseleave="reservationBy"/>
If using v-model is not an option (that would be the easiest way), and you want to execute the function when component is rendered, you can use ref and access value in mounted hook:
<input ref="myInputRef" :value="2" />
Script:
mounted: function() {
console.log(this.$refs.myInputRef.value);
}

Vuejs why all the methods are called?

In the following code first tag p renders name and it is also binded to input event of input field.
There is method called random and it generates random number. And it is rendered in the last p tag. Wondering why random method is being called for every character input in the input box? Shouldn't that be executed only one?
I know I can add Vuejs directive v-once to the last p tag and it stays the same.
Can anyone help me understand this better?
Vue.config.devtools = false
Vue.config.productionTip = false
new Vue({
el:"#exercise",
data: {
name: "Tokyo",
},
methods: {
changeName: function(event){
this.name = event.target.value;
},
random: function(){
return Math.random();
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="exercise">
<p>VueJS is pretty cool - {{ name }}</p>
<br/>
<input type="text" v-bind:value="name" v-on:input="changeName">
<br/>
<p>{{random()}}</p>
</div>
It updateds because its binded to your vue instance. Whenever name changes it will automatically change in the DOM.
With every key press you trigger the method changeName. Now changeName changes name. Vue.js detect this change and update your DOM.

2 way binding is not working properly in vuejs

I have defined a vuejs component this way:
<template>
<form #submit.prevent="submit">
<textarea id="content" cols="30" rows="10" v-model="content">{{ content }}</textarea>
<button class="btn btn-lg btn-success" type="submit" #click="send()">
Send content
</button>
</form>
</template>
<script>
export default {
data() {
return {
content: '// Initial content'
}
},
methods: {
send() {
console.log('Content', this.content);
},
submit() {
return false;
}
},
mounted() {
console.log('Template init ', this.content);
}
}
</script>
When I click on send, the send method outputs the content of the textarea as expected. But when I change the content of the textarea with jquery:
$('#content').val(content);
and hit send, it doesn't update content in the template. "Send" outputs the old value.
can somebody please explain to me what's wrong here?
v-model is listening for an input event to trigger changing the value of its bound variable.
From the vue.js documentation:
v-model internally uses different properties and emits different
events for different input elements:
text and textarea elements use value property and input event;
checkboxes and radiobuttons use checked property and change event;
select fields use value as a prop and change as an event.
Using the JQuery val() method to select the element and change the value does not trigger an event that v-model is listening for, so the value of your bound variable does not change/update.
If you absolutely have to use JQuery to change the content, you could manually trigger an event that might also trigger the v-model binding to update:
$('#content').val(content).trigger('input');

Vue.js showing div on input event deletes text from input

I am struggling with the following, trying to get a div to show up underneath a text input after someone begins typing in the input:
https://jsfiddle.net/chadcf/3vjn71ap/
The template is:
<div id="app">
<input id="foo"
name="foo"
:value="localValue"
type="text"
placeholder=""
autocomplete="off"
#input="handleInput"
>
<div v-if="show">Testing</div>
</div>
With the following vue code:
new Vue({
el: "#app",
data() {
return {
show: false,
localValue: null
}
},
methods: {
handleInput(e) {
this.show = true;
},
}
});
When you run this, if you type a character in the text input, indeed the div underneath shows up. But in addition the character you just typed vanishes. After that first character though everything works fine.
I think what's going on here is that when the input starts and sets this.show = true, that's happening before the value actually updates. I think... And thus vue re-renders the input but with no value. But I'm not actually sure what to do to handle this properly...
This is happening because localValue isn't being updated by your input. When you start typing show will be set to true, so Vue will update the DOM to show your hidden div. But since localValue is null when the DOM updates your input will be blank since its value is bound to localValue. You can verify this by making handleInput toggle show's value instead of setting it to true and you'll see that every time you type something in the input field the hidden div's visibility will be toggled when the DOM updates but the input will be cleared ..
methods: {
handleInput(e) {
this.show = !this.show;
},
}
So to solve this you'll have to make sure that localValue is being updated by your input. The easiest way is to use v-model ..
<div id="app">
<input id="foo"
name="foo"
v-model="localValue"
type="text"
placeholder=""
autocomplete="off"
#input="handleInput"
>
<div v-if="show">Testing</div>
</div>
JSFiddle
Alternatively you can manually handle the input in your handleInput method and set localValue to the typed value like Austio mentioned in his answer.
Hey so you are pretty close on this thought wise. When you handle input yourself, you have to set the new value when you have new input. In your specific case localValue will always be null which is not what i think you want. I think you are wanting something more like this.
methods: {
handleInput(e) {
this.localValue = e.target.value;
this.show = true;
},
}