I am trying to implement an on-screen keyboard for entering numbers into various input fields. In a real project, there are several dozen of them. I save the active field through focus and when I click on a number, it is added to the end of the field value. But when I change the value of the input, the value of the bound v-model does not change. Although, when I enter from a regular keyboard, everything changes normally. I am attaching the example code
<template>
<p>xSize</p>
<input v-model="xSize">
<p>ySize</p>
<input v-model="ySize">
<div class="keyboard">
<button v-for="i in [1,2,3,4,5,6,7,8,9,0]" class="key" :key="i" @click="addChar(i)">{{i}}</button>
</div>
<p>xSize = {{xSize}}</p>
<p>ySize = {{ySize}}</p>
<div class="test-box" v-bind:style="{width: this.xSize + 'px', height: this.ySize + 'px'}"></div>
</template>
<script>
export default {
data: function () {
return {
xSize: 50,
ySize: 50,
activeElement: null
}
},
props: {
},
created() {
document.addEventListener('focusin', this.focusChanged)
},
beforeUnmount() {
document.removeEventListener('focusin', this.focusChanged)
},
methods: {
focusChanged: function (event) {
const el = event.target
if (el.type === "text") {
if (this.activeElement !== el && this.activeElement !== null) {
this.activeElement.style.background = "white";
}
this.activeElement = el
this.activeElement.style.background = "red";
}
},
addChar: function (char) {
if (this.activeElement !== null) {
this.activeElement.value += char
}
}
}
}
</script>
<style scoped>
.keyboard {
display: flex;
}
.key {
margin: 3px;
width: 30px;
height: 30px;
border: 2px black ridge;
}
.test-box {
border: 2px black ridge;
background: red;
margin: 15px;
}
</style>
Because what you modified was only the value of the element, not the responsive data in the data.
You can change the code to this way.
<template>
<p>xSize</p>
<input v-model="xSize" data-name="xSize">
<p>ySize</p>
<input v-model="ySize" data-name="ySize">
<div class="keyboard">
<button v-for="i in [1,2,3,4,5,6,7,8,9,0]" class="key" :key="i" @click="addChar(i)">{{i}}</button>
</div>
<p>xSize = {{xSize}}</p>
<p>ySize = {{ySize}}</p>
<div class="test-box" v-bind:style="{width: this.xSize + 'px', height: this.ySize + 'px'}"></div>
</template>
<script>
export default {
data: function () {
return {
xSize: 50,
ySize: 50,
activeElement: null
}
},
props: {
},
created() {
document.addEventListener('focusin', this.focusChanged)
},
beforeUnmount() {
document.removeEventListener('focusin', this.focusChanged)
},
methods: {
focusChanged: function (event) {
const el = event.target
if (el.type === "text") {
if (this.activeElement !== el && this.activeElement !== null) {
this.activeElement.style.background = "white";
}
this.activeElement = el
this.activeElement.style.background = "red";
}
},
addChar: function (char) {
if (this.activeElement !== null) {
const fieldName = this.activeElement.getAttribute("data-name");
this[fieldName] += char
}
}
}
}
</script>
<style scoped>
.keyboard {
display: flex;
}
.key {
margin: 3px;
width: 30px;
height: 30px;
border: 2px black ridge;
}
.test-box {
border: 2px black ridge;
background: red;
margin: 15px;
}
</style>