I'm trying to implement a slack like feature to send a message only when pressing exact enter (without shift pressed)
Considering this vue template <textarea type="text" v-model="message" @keyup.enter.exact="sendMessage($event)"></textarea>
with this component
export default { name: 'Typing', data() { return { message: null } }, methods: { sendMessage(e) { // e.stopPropagation() and e.preventDefault() have no impact this.$socket.emit('message', { text: this.message }); console.log(this.message); // Print the message with another '\n' at the end due to textarea default behavior } } }
Does anyone has an idea of how I can avoid having the last '\n' without using a regex to delete it before sending it to the backend (which I think will be dirty) ?
Thank you
PS : I'm pretty new to VueJS stack and hope that my question is not obvious
EDIT: This question is similar but the proposed solution is not working
<textarea type="text" v-model="message" @keyup.enter.exact="sendMessage($event)" > </textarea>
The code calls the sendMessage
method on the keyup
event of the Enter key. The keyup
event is fired after the key has been released. Therefore the code is calling the method after the key has been pressed, after the default behaviour of the key run (entering a newline) and after the key has been released. preventDefault
will not prevent the problem as the behaviour trying to be prevented has already occurred, before the keyup
event.
As we have identified the following:
keyup
event is fired after the default behaviour has already occurred.The solution is to prevent the default behaviour on the keydown
event and call the method on the keyup
event.
Note: it is important to only call the method on the
keyup
event to avoid multiple calls if the user holds down the key.
<textarea v-model="value" @keydown.enter.exact.prevent @keyup.enter.exact="send" @keydown.enter.shift.exact="newline" > </textarea>
A method which appends a newline to the textarea value can be called when the Enter+Shift combination is pressed.
Below is a snippet demonstrating all the behaviours described in the solution.
new Vue({ template: ` <div> <textarea v-model="value" @keydown.enter.exact.prevent @keyup.enter.exact="send" @keydown.enter.shift.exact="newline" > </textarea> </div> `, data: { value: '', }, methods: { newline() { this.value = `${this.value}\n`; }, send() { console.log('========'); console.log(this.value); console.log('========'); }, }, }).$mount('#root');
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> </head> <body> <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script> </body> </html>
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