When I use custom directive to change component's value, there is not effect:
Vue.directive('maxchars', {
bind(el, binding, vnode) {
let maxChars = binding.value;
let handler = function(e) {
if (e.target.value.length > maxChars) {
e.target.value = e.target.value.substr(0, maxChars)
}
}
el.addEventListener('input', handler);
}
});
let app = new Vue({
el: '#app',
data() {
return {
content: '',
totalCount: 140
}
}
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id='app'>
<div>
<div class='content'>
<textarea v-model='content' v-maxchars='140'>tell me something</textarea>
</div>
</div>
</div>
when I use v-bind:input directive to change value is ok!
The combination of the v-model and computed property makes your code robust and more reusable. Hope this article helps you to understand how to use two-way data binding in Vue. js by using the v-model directive and computed properties.
The v-model is a two-way binding which means if you change the input value, the bound data will be changed. The v-model directive is used to create two-way data bindings on form input, textarea, and select elements. Example: HTML.
You can use v-model with a custom Vue component by accepting a prop named 'value' and emitting an event named 'input'. For example, the below custom component is a fake select using div elements. Clicking on a div selects it.
but v-bind:value is called one way binding that means: you can change input value by changing bound data but you can't change bound data by changing input value through the element. ' if you change input value, the bound data will be changed and vice versa.
First:
v-model, the value of the textarea will be whatever is in the v-model's variable (in this case, the variable content). This means that the initial value of the DOM is ignored.content in data().Second:
.value directly. v-model actually watches for input✱ events from the DOM element.
change event, or othervalue, Vue will simple override it back (to whatever is in content) next time an update happens.After changing the .value, trigger input event. Vue will pick the event up and update the v-model variable from the current .value before it overrides it.
Demo:
Vue.directive('maxchars', {
bind(el, binding, vnode) {
let maxChars = binding.value;
let handler = function(e) {
if (e.target.value.length > maxChars) {
e.target.value = e.target.value.substr(0, maxChars);
vnode.elm.dispatchEvent(new CustomEvent('input')); // added this
}
}
el.addEventListener('input', handler);
}
});
let app = new Vue({
el: '#app',
data() {
return {
content: 'tell me something',
totalCount: 140
}
}
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id='app'>
<div>
<div class='content'>
<textarea v-model='content' v-maxchars='18'></textarea>
</div>
<pre>
content: {{ content }}
Max chars is 18, current is {{ content.length }}.
</pre>
</div>
</div>
Just create a input event using Event function.
var event = new Event("input", { bubbles: true });
then modify the value and then dispatch the event, it will update the v-model value
el.dispatchEvent(event);
Vue.directive('maxchars', {
update(el, binding, vnode) {
var event = new Event("input", { bubbles: true });
let maxChars = binding.value;
if (el.value.length > maxChars) {
el.value = e.value.substr(0, maxChars);
el.dispatchEvent(event);
}
}
});
hope it will helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With