简体   繁体   中英

event prevent default not working within VueJS instance

I'm trying to disable a form submission when the enter key is pressed. The approaches I've tried are listed below with the code and example demo.

EXAMPLE OF PROBLEM HERE

Desired outcome: Focus on the input, press down -> down -> enter and it should log the index of the record you have selected and stop there.

What's actually happening: It logs as expected, but then reloads the page immediately as the form submits.

HTML

<form action="/some-action" @submit.stop.prevent="prevent">
  <div class="auto-complete" v-cloak>
    <div class="ico-input">
      <input type="text" name="search" placeholder="Enter text" @keyup.prevent="handleKeypress">
    </div>
    <ul class="raw auto-complete-results">
      <li v-for="r in results" @click="loadSelection($index)" v-bind:class="{'selected': selectedIndex == $index}"><span>{{ r.name }}</span></li>
    </ul>
  </div>
</form>

JS

var autocomplete = new Vue({
  el: '.auto-complete',
  data: {
    results: [{name: 'swimming1'}, {name: 'swimming2'}, {name: 'swimming3'}, {name: 'swimming4'}, {name: 'swimming5'}, ],
    selectedIndex: -1,
  },
  methods: {
    handleKeypress: function(event) {
      event.preventDefault();
      event.stopPropagation();

      var key = event.which;

      if ([38, 40].indexOf(key) > -1) //handle up down arrows.
        this.arrowNavigation(key);

      else if (key == 13) //handle enter keypress
        this.loadSelection(this.selectedIndex);

      return false;
    },

    arrowNavigation: function(key, target) {
      if (key == 38) //up
        this.selectedIndex = this.selectedIndex - 1 < 0 ? 0 : this.selectedIndex - 1;
      if (key == 40) //down
        this.selectedIndex = (this.selectedIndex + 1) > (this.results.length - 1) ? 0 : this.selectedIndex + 1;
    },

    loadSelection: function(index) {

      if (index < 0 || index > this.results.length)
        return false;

      var selection = this.results[index];
      console.log("loading selection", index,selection);
    },

    prevent: function(event) {
      event.preventDefault();
      event.stopPropagation();
      return false;
    },
  }
})

I've tried various syntax approaches on both form/input (switching submit for keyup on the input)

  • v-on:submit="prevent"
  • @submit
  • @submit.stop
  • @submit.prevent
  • @submit.stop.prevent="prevent"

I've also tried calling the following from with in the 2 event handlers aswell as returning false from them both.

  • event.preventDefault()
  • event.stopPropagation()

The form still triggers a page reload no matter what I try. I can't see anything obviously wrong so I turn to stackoverflow to guide my eyes.

Thanks

This Answer to another question suggests that forms with a single input element always get submitted, not matter what you do.

And indeed adding another input (and hiding it) helped.

https://jsfiddle.net/Linusborg/Lbq7hf1v/1/

<div class="ico-input">
  <input type="text" name="search" placeholder="Enter text" @keyup.prevent="handleKeypress">
  <input type="text" hidden style="display:none;">
</div>

Browsers are stupid.

Note that, anything outside of the el that you use to reference your Vue instance will not be recognized by vue no matter how correctly you define your event modifiers on your elements.

In your example you are referring to your Vue instance through the .auto-complete element which is a child of the form element which the submit event is bound to by default. Any event modifiers added to your form will never take effect. Try wrapping all your HTML in a div and reference vue through that, like so:

HTML

<div id="app">
    <!-- HTML/Vue Directives/Mustache here -->
    <form action="/some-action" @submit.stop.prevent="prevent"> 
        ... rest of your code ...
    </form>
</div>

JS:

var autocomplete = new Vue({
    el: '#app',
    data: { 
        ... rest of your js code ...
})

Also Vue devtools can be very useful when debugging such situations.

Try this!

<form @submit.prevent>

Works for Vue2

Try @keydown.enter.prevent I was having the same problem but I was using keyup

<input type="text" @keydown.enter.prevent="doSomething" />

You don't have to have a method either if you just want to stop the form from submitting just put @keydown.enter.prevent without a method.

<input type="text" @keydown.enter.prevent />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM