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