How can I write a Vue 2.x directive in such a way that it can detect changes in the model? I can only bind to the element and detect input, keydown, etc. But i can't detect when the model was updated. Is this out of scope for Vue's directives?
Vue.directive('text-validation', {
bind: function (el, binding, vnode) {
el.addEventListener('input', function(){
console.log('only gets called on input, not model updates');
});
}
});
new Vue({
el: '#app',
data: {
text: 'testing...'
},
mounted: function() {
setTimeout(function(){
this.text = 'detected change';
}.bind(this), 2000)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div id="app">
<input v-model="text" v-text-validation=""/>
</div>
Ah, I forgot what the update
hook is for. I created a working snippet, that does what I intended - an update on model calls the update hook
Vue.directive('text-validation', {
bind: function (el, binding, vnode) {
el.addEventListener('input', function(){
console.log('got called');
});
},
update: function(el, binding, vnode) {
console.log('got called on upadate');
}
});
new Vue({
el: '#app',
data: {
text: 'testing...'
},
mounted: function() {
setTimeout(function(){
this.text = 'detected change';
}.bind(this), 2000)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div id="app">
<input v-model="text" v-text-validation=""/>
</div>
EDIT
I ended up setting up a watch() inside the bind() hook. Firing any kind of DOM native events from inside of update() was causing all sorts of infinite loops.
Pseudocode:
var modelExp = vnode.data.directives.find(d->d.name === 'model');
vnode.context.$watch(modelExp, function(){//do what i need}, {deep, true});
This was borrowed from "VeeValidate" project, ListenerGenerator.prototype._attachModelWatcher
As @Bert pointed out - you can/could use watchers for that (if you do not need something more advanced - as central state / store Vuex etc.).
With watchers - it is very important to note that you can use them with "deep: true," that watches children inside objects;
watch: {
myData: {
handler: function (newVal, oldVal) {
// we have new and old values
},
deep: true /* we will be notified of changes also if myData.child is changed :) */
}
}
State is more complicated but can be a saviour if app is getting more and more complex...
Found this usefull and simple demo: Vue - Deep watching an array of objects and calculating the change?
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