Reputation: 2555
with v-model
it is possible to bind a property of a reactive object to an html component
<input v-model="myObject.property" />
however, when I bind myObject.property
to my custom directive:
<input v-customDirective="myObject.property" />
the value is accessible through binding.value
- and this value is not reactive
I was trying to find out how they do it in vue - but I was not successful. How would it be possible to achieve a v-model like data binding?
Update:
I get an myObject.property
change on the updated(el, binding, vnode, prevVnode)
function. But I want to
directives: {
'custom-input': {
created(el, binding) {
el.value = binding.value;
el.addEventListener('input', () => {
// ---- this does not work ------
binding.value = el.value;
});
},
updated(el, binding) {
console.log('Value has updated', binding.value);
}
},
},
Upvotes: 0
Views: 85
Reputation: 23602
You can't achieve what you want with this syntax, since the myObject.property
is unwrapped and passed as by value to the directive and you cannot change any variable passed by value in JS.
Moreover myObject.property
string isn't available at runtime and you can't guess the source of the directive's value.
The only way is to achieve your syntax is to make a Vue/Vite plugin to compile your directive to whatever you want (I did that to achieve behavior not possible with runtime directives only).
The closest what you want could be done with providing a ref bound to an object's property:
<script setup>
import { reactive , toRef } from 'vue'
const myObject= reactive({property: 'Hello World!'});
const vCustomDirective = {
mounted(el, {value}){
el.value = value.value;
el.addEventListener('input', e => value.value = el.value);
},
updated(el, {value}){
el.value = value.value;
}
}
</script>
<template>
<h1>{{ myObject }}</h1>
<input v-customDirective="toRef(myObject, 'property')" />
<button @click="myObject.property = 'Clicked button'">Change property</button>
</template>
Alternative:
<script setup>
import { reactive , toRef } from 'vue'
const myObject= reactive({property: 'Hello World!'});
const vCustomDirective = {
mounted(el, {value: [myObject, property]}){
el.value = myObject[property];
el.addEventListener('input', e => myObject[property] = el.value);
},
updated(el, {value:[myObject, property]}){
el.value = myObject[property];
}
}
</script>
<template>
<h1>{{ myObject }}</h1>
<input v-customDirective="[myObject, 'property']" />
<button @click="myObject.property = 'Clicked button'">Change property</button>
</template>
Upvotes: 0