Reputation: 10771
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.
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)
I've also tried calling the following from with in the 2 event handlers aswell as returning false from them both.
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
Upvotes: 3
Views: 16993
Reputation: 392
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 />
Upvotes: 0
Reputation: 23968
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.
Upvotes: 4
Reputation: 317
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:
<div id="app">
<!-- HTML/Vue Directives/Mustache here -->
<form action="/some-action" @submit.stop.prevent="prevent">
... rest of your code ...
</form>
</div>
var autocomplete = new Vue({
el: '#app',
data: {
... rest of your js code ...
})
Also Vue devtools can be very useful when debugging such situations.
Upvotes: 2