admin管理员组

文章数量:1287526

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 oute: 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-plete" v-cloak>
    <div class="ico-input">
      <input type="text" name="search" placeholder="Enter text" @keyup.prevent="handleKeypress">
    </div>
    <ul class="raw auto-plete-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 autoplete = new Vue({
  el: '.auto-plete',
  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

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 oute: 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-plete" v-cloak>
    <div class="ico-input">
      <input type="text" name="search" placeholder="Enter text" @keyup.prevent="handleKeypress">
    </div>
    <ul class="raw auto-plete-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 autoplete = new Vue({
  el: '.auto-plete',
  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

Share Improve this question edited Jul 12, 2016 at 11:44 Kiee asked Jul 12, 2016 at 11:36 KieeKiee 10.8k8 gold badges35 silver badges56 bronze badges 1
  • I'm having the same problem. In my case, I'm parsing the form from an external source back into Vue. I guess in this case it doesn't recognize the form? This is strange, since if I set a breakpoint in the Vue file, it hits the breakpoint in Chrome. – Allen Wang Commented Apr 13, 2018 at 20:14
Add a ment  | 

4 Answers 4

Reset to default 4

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/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-plete 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 autoplete = 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 />

本文标签: javascriptevent prevent default not working within VueJS instanceStack Overflow