Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS: How to prevent textarea default behavior

Tags:

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

like image 801
Pierre Clocher Avatar asked Nov 10 '17 10:11

Pierre Clocher


1 Answers

Problem

<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.

Solution

As we have identified the following:

  • We wish to prevent the default behaviour of pressing the Enter key.
  • The 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>

Further reading

  • W3C Specification for Keyboard Events
  • Specifically event order and event types
like image 160
Wing Avatar answered Nov 01 '22 01:11

Wing