My question is about react, onSubmit and preventDefault.
I've got a form, which handles between 2 - 4 steps of user input depending on certain cases.
<Form>
{StepRendersHere}
</Form>
The form has a onSubmit event that prevents default (and stopPropagation).
When using the button for "next step" the event fires, and the form is NOT submitted.
But when using the enter key, the event is fired, but the form is posted. This results in the site refreshing with the form data as url parameters.
The weird thing is that if none of the buttons in the form has type="submit". The onSubmit doesn't even fire on enter key.
isDefaultPrevented returns true in both cases.
Any hints/thoughts on how I can prevent the form from posting when pressing enter? My issue is with Enter key posting the form, despite preventDefault.
Have tried binding the enter key to a event that prevents default, doesn't work. Might have done it the wrong way though.
UPDATE (implementation)
<Form onSubmit={this.inc_step} id="applicationform">
{FormStepRenderedHere}
</Form>
inc_step = e => {
e.preventDefault();
e.stopPropagation();
alert( e.isDefaultPrevented() )
let new_step = this.state.current_step + 1;
alert('INSIDE INC STEP');
if (this.validateForm()) {
this.setState({
current_step: new_step
})
}
}
UPDATE (FIXED IT)
I found a solution, and want to share if anyone else has the same problem.
My solution however might be unique to semantic ui, which i'm using. I solved it by putting as={Form.Group} on the form, mening it wont render as a form, with its standard events, such as enter key submit. Now the enter key does nothing, as I wanted it.
Thank you for the comments!
A much easier way to accomplish this is to add a button element to your form and add the display none css attribute (if you don't want to see the button).
The button automatically adds the ability to use the enter key with onSubmit.
I found a solution, and want to share if anyone else has the same problem.
My solution however might be unique to semantic ui, which i'm using. I solved it by putting as={Form.Group} on the form, mening it wont render as a form, with its standard events, such as enter key submit. Now the enter key does nothing, as I wanted it.
So actually not rendering the form as a form to begin with was the solution.
Related
Using Javascript, no framework, what button event should I use to confirm form when I wish not redirect? I expect to use either left mouse button or keyboard to confirm the form.
I used this element:
<button type="button" value="1">Save</button>
Using type="submit" with "submit" event is no solution for me because this creates redirection (values the from are lost). So I use type "button".
When I use
document.getElementById("advanced_form").addEventListener("click", saveOptions);
This even "click" is used with mouse. But there is possibility that the user will use keyboard instead mouse to submit form. So I suspect the form would not react to keyboard confirm action. I did not find any event related to button being pressed. So how to solve this problem?
You could still use ´type="submit"´ in combination with ´e.preventDefault();´ to aviod the redirect.
I hope this helped, good luck.
From your clarifying comment:
What happened is when I clicked the button the values which were in the form disapeared and so I understood it that the form was reloaded without any values.
Submitting a form...submits the form. What you get back as a result depends entirely on what the server sends back.
But the values should not disappear, the behaviour which I need is like in a normal Browser Window (WINAPI)
That is normal.
...the page will not clear the values. If I'd want to close the form, I'd close the tab (html page).
That isn't normal. Normal is for the form to go away and be replaced by the result of submitting it.
But you can do that with the submit event, just use event.preventDefault() within the submit event to prevent the form submission:
document.getElementById("the-form").addEventListener("submit", function(event) {
event.preventDefault(); // Prevents the form from being submitted
});
That event will reliably fire whether the user used the mouse, keyboard, or assistive technology to submit the form. The click event on a submit button will not reliably fire when the form is submitted with the keyboard or assistive technology.
You can use submit button, but you need to handle submit action. Try this (with jquery):
<input class="submit_button" type="submit" value="Save" />
<script>
function submit_form(e)
{
if (check_form_submit()) {
// check your data here
$(this).submit();
return;
}
e.preventDefault();
}
$(function() {
$('.submit_button').parents('form').submit(submit_form);
});
</script>
You should still use the submit input type but you need to prevent the default action so that the page doesn't reload.
If you are using jQuery this snippet should help.
$('#my-form').submit(function(ev) {
ev.preventDefault(); // to stop the form from submitting
// Your code here
this.submit(); // If you want to submit at the end
});
I'm using Bootstrap's modal component to create an "Add User" dialog to my web app. To make it easy for users to work quickly I want to make the escape an enter keys close and submit the form as would be expected. After running into the usual troubles of divs not accepting input, and some elements under the modal getting focus I ended up just hooking a keypress event to 'document'. This actually works great with one exception.
When entering data into the form the browser will sometimes show a suggestion box:
Hitting escape to close the suggestion box, or enter to select an element from it will unfortunately trigger a keypress event which causes the form to be closed or submitted.
Is there a way I can ignore the keypresses in this situation? Do I need to be taking a completely different approach?
An alternative approach would be to add autocomplete="off" into the input tag.
Did you use $(document).keyUp() to bind your ESC and Enter key event. If so, you can try to add this code in that function to ignore keypress which pressed in a input tag:
$(document).keyup(function(e){
if(e.srcElement.tagName == 'INPUT'){
return;
}else{
// Your code to bind function to exit div or submit
}
});
I apologise in advance for not being able to provide any actual code, as the problem appears in a page which is currently private :-/ Please bear with me.
I have an HTML form. I attached a (proprietary) calendar widget to one of the text input fields. When the user tabs into the field the calendar appears. On the calendar there are a couple of buttons (to move to the previous/next month). When the user clicks on one of these buttons the calendar updates itself accordingly, but also - the form submits! There's NOTHING in the calendar code that touches anything other than the calendar itself and the text input field it is attached to, let alone submits a form! I would appreciate any clue regarding any of the following questions:
1) What could possibly have submitted the form in such a setting?
2) What things generally submit a form, other than clicking on the submit button or hitting the enter key? (In particular, do ordinary buttons submit forms? Under which circumstances?)
3) As a workaround in case I don't manage to figure this out, is there a way to simply totally disable submitting the form (and then reenable it in an event handler attached to the submit key)?
Note(s): The calendar behaves normally other than that - responds normally to key events and to click events on the dates themselves (which are not buttons). I tried this on both Firefox and Chrome and got the same behaviour. I tried to follow the click event handler step-by-step with FireBug, and everything seemed perfectly normal - but the moment it finished the form was submitted (and the page reloaded). The widget uses jQuery 1.7.2. Any help in understanding and/or solving this will be most appreciated!
Sorry to answer my own question, but none of the given answers was complete, even though I've learnt from them and from the comments! Thanks for everyone who participated!
So:
1+2) Buttons defined by the <button> element cause submits (as if they had type="submit" set. At least in some browsers). If one wants a button not to cause a submit one should use <button type="button">, or the good old <input type="button" />.
3) (Unnecessary for me now, but it was part of the question.) There are many ways to prevent a form from submitting. Three of them are:
to handle the onsubmit event, preventing the submit (by return false; or - preferably! - by e.preventDefault();) in case a flag is not set; set the flag when handling the event(s) that should actually submit the form
to handle the onsubmit event and prevent the submit as above if the element that triggered the event is not (one of) the element(s) we want to cause a submit
to set the form action to non-action, i.e. action="#", and to have the handler for the event that should actually submit the form set the action to the proper address
The calendar can submit your form in its JavaScript source code by calling form's submit() method using jQuery or plain JavaScript.
Here is an example how to disable the form submit and allow it only in case of pressing the button.
<form id="form">
<input type="text" />
<input type="button" name="submit-button" value="Submit"/>
</form>
<script type="text/javascript">
var form = document.getElementById('form'),
button = form['submit-button'];
form.onsubmit = function(e) {
return !!form.getAttribute('data-allow-submit');
};
button.onclick = function() {
form.setAttribute('data-allow-submit', 1);
form.submit();
};
</script>
Demo
The calendar code isn't calling submit() somewhere?
3) As a workaround in case I don't manage to figure this out, is there a way to simply totally disable submitting the form (and then reenable it in an event handler attached to the submit key)?
Unfortunately, I'm not totally sure if it's reliable that the click handler will be called before the form submit event.
( function () {
var prevent_submit = true;
$( "form" ).on( 'submit', function ( event ) {
if ( prevent_submit ) {
event.preventDefault();
}
} );
$( "input[type='submit']" ).on( 'click', function ( event ) {
prevent_submit = false;
} );
} )();
or
$( "form" ).attr( { action : "#", method : "post" } );
$( "input[type='submit']" ).on( 'click', function ( event ) {
event.target.form.action = "...";
} );
Hitting enter on text fields can sometimes trigger a form submit. See here. Especially if that is the only element in the form. One way to control the post back is to set the action to empty and fire off the event yourself with Javascript.
Check the placement of the closing form tags. I had this problem once and I finally figured out that there was some 'permissions' code within the form itself that prevented the user from reaching the closing tag because he didn't have the proper permission level to submit it. In effect this left an open form tag that then responded to other buttons elsewhere on the same page.
I have a search form:
<form class="searchForm" id="topSearchForm" action="/search.ds">
that has an onsubmit-event attached to it, triggering a javascript. The purpose of this javascript is to empty certain form-fields before submission of the form based on certain criteria.
To be clear, what needs to happend is:
User input -> User clicks search button (or presses "enter") -> Javascript runs -> fields are cleared -> form is submitted
This works exactly as intended in all browsers except in IE7 and IE8. The javascript runs but for some reason the form submission is done before the fields are being cleared by the javascript. This causes the submitted page to include the data from fields that were supposed to be cleared.
I only have control of (certain parts of) the UI and cannot handle anything after the submission of the form. For usability purpose it is important that these fields (that should be cleared) are filled out up until the user submits the form.
Why is the internal logic different in IE7 & IE8 (it works fine in IE9 and "all other browsers)? Is there a way for me to circumvent this issue?
Here are some more code to clarify:
I attach the event to the form:
var formElement = document.getElementById("topSearchForm");
[...]
formElement.attachEvent('onsubmit', function() {clearForSubmit()});
and clearForSubmit is defined and is triggered.
You can try something like this in the js
<form onsubmit="clearForSubmit(); return false;">
this will NOT submit the form, you can submit the form after you clear it with
form_name.submit();
Use an onclick event instead of onsubmit, then submit the form at the end of the function in code.
This is driving me nuts. Its a tough one to explain but I'll have a go.
I have one input text field on the front page of my site. I have coded a keydown event observer which checks the keyCode and if its ENTER (or equiv), itll check the input value (email). If the email is valid and unique in the DB itll submit the form. Basic stuff, or so you would think.
If I type my email address in the field and hit enter, it works fine in all browsers. However, if I type the first couple of letters, and then use the arrow keys to select the email from the history dropdown box (hope you know what I mean here), and then press enter the result is different. The value of the form field is being captured as just the couple of letters I typed, and therefore the validation is failing. It seems that when I press the enter key to "select" the email from the history dropdown, the browser is interrupting that as if I was typing.
In Chrome and Safari it works as it should. As it should means that when you press enter to "select" the email from the history dropdown, all it does is puts that email address into the text box. Only on the second ENTER key press does it then trigger the event observer, and the email is validated.
Hope somebody can shed some light on why this is happening... My gut feeling is its a browser thing and will be something I cant fix.
Thanks
Lee
EDIT:
To add clarification to my question let me add that Im using the "keydown" event to capture the moment when the enter key is pressed. I have tried the "keyup" event and this solved my problem above, but then I cant seem to stop the form submitting by itself. The "keyup" event triggers AFTER the default behaviour, therefore its not the right choice for this.
FURTHER EDIT:
Thank you again, and btw, your English is excellent (in response to your comment about bad English).
I have changed my event handler from this:
$("emailInputBox").observe("keydown", function(event) {
return submitViaEnter(event, submitSignupFormOne);
});
to this:
$("emailInputBox").observe("keydown", function(event) {
setTimeout(submitViaEnter.curry(event, submitSignupFormOne),0);
});
submitViaEnter:
function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
event.stop();
return callback(event);
}
return true;
}
Seems to work but the problem now is that the browser is permitted to carry out the default action before running the submitViaEnter function which means the form is being submitted when I hit ENTER.
Answer to the original question
Yeah, it's a Gecko bug (not Mac-specific though).
The last part of this comment contains the description of the work-around: use the time-out.
[edit] since you asked for the clarification of the bug
When you press Enter and the auto-complete is active, Firefox (erroneously) first fires the page's key handler, then the browser's internal key handler that closes the autocomplete popup and updates the text area value, while it arguably should just fire it at the autocomplete popup and only let the page know the textbox value changed.
This means that when your key handler is called, the autocomplete's handler hasn't run yet -- the autocomplete popup is still open and the textbox value is like it was just before the auto-completion happened.
When you add a setTimeout call to your key handler you're saying to the browser "hey, run this function right after you finished doing stuff already in your P1 to-do list". So the autocomplete's handler runs, since it's already in the to-do list, then the code you put on a time-out runs -- when the autocomplete popup is already closed and the textbox's value updated.
[edit] answering the question in "Further edit"
Right. You need to cancel the default action in the event handler, not in the timeout, if you want it to work:
function onKeyPress(ev) {
if (... enter pressed ...) {
setTimeout(function() {
... check the new textbox value after letting autocomplete work ...
}, 0);
// but cancel the default behavior (submitting the form) directly in the event listener
ev.preventDefault();
return false;
}
}
If you still wanted to submit the form on Enter, it would be a more interesting exercise, but it doesn't seem you do.
ok sorted it. Thanks so much for your help. It was the curry function that I was missing before. I was trying to work on the event inside the scope of the setTimeout function.
This works below. The submitViaEnter is called from the eventobserver and responds to the keyDown event:
function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
event.stop();
setTimeout(callback.curry(event),0);
// return callback(event);
// return false;
}
return true;
}
Stopping the default action inside the eventObserver meant that no characters could be typed. So I stuck inside the if ENTER key clause.