Reputation: 6749
I try to use the method setSelectionRange
to change the position of the cursor in a vuetify v-textarea
.
It works well when I do not manipulate the data element referred by the v-model
attribute of the textarea. However, if I attempt to change the body first, and then apply the setSelectionRange
method; the cursor moves directly to the end of the text.
I'm attaching a snippet of a simplified version. Once you hit backspace key on anywhere in the textarea and the cursor should move to index 2; but it moves to the end of the text instead.
If you remove this.body
and backspace again, however, it peacefully moves to index 2.
new Vue({
el: '#app',
data: {
body: ''
},
created () {
this.body = 'I am initial body. Hit backspace on somewhere if you want!'
},
methods: {
onBackspaceOrDeleteButtonKeydown (event) {
// disable default behavior
event.preventDefault()
let bodyTextArea = this.$refs.pourBody.$el.querySelector('textarea')
// COMMENT OUT THE NEXT LINE TO SEE THE CURSOR MOVES TO INDEX 2 ALWAYS
this.body = 'I am changed body. My cursor should have moved to index 2 anyways, but it goes to the end like >'
bodyTextArea.setSelectionRange(2, 2)
}
}
})
<!DOCTYPE html>
<html>
<head>
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app>
<v-content>
<v-container>
<v-textarea
ref="pourBody"
outline
v-model="body"
auto-grow rows="7"
@keydown.delete="onBackspaceOrDeleteButtonKeydown"
></v-textarea>
</v-container>
</v-content>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
</body>
</html>
The setSelectionRange
does not like body change apparently.
How can I work around it?
Upvotes: 2
Views: 3487
Reputation: 61
In addition to givehug's solution you can also do
this.$nextTick(() => {
bodyTextArea.setSelectionRange(2, 2))
})
Upvotes: 4
Reputation: 2011
Wrap setSelectionRange into setTimeout, like so setTimeout(() => bodyTextArea.setSelectionRange(2, 2))
. Value is rerendered by v-model after you set cursor to desired position and cursor position is reset. You have to make sure you call setSelectionRange
afterwards.
Upvotes: 10