Two submit buttons in one form. Can event in submit function know which one?
Asked Answered
T

5

0

I was wonder if in JQuery, this is possible:

<form id="testform">
    <input type="text" id="hi" name="hi" />
    <input type="text" id="bye" name="bye" />

    <button type="submit" id="submit1">Use Me</button>
    <button type="submit" id="submit2">No, Use Me </button>
</form>


$('#testform').submit(function(e) {

    e.preventDefault();

    var submiturl;

    if (e.name === 'submit1') { submiturl = '../sendToFactory.cshtml'; }
    else if (e.name === 'submit2') { submiturl = '../sendOverseas.cshtml'; }

    $.ajax({
        url: submiturl,
        data: $('testform').serialize(),
        type: 'POST',
        datatype: 'json',
        success: function (response) {
            //stuff
        },
        error: function (response) {
            //error
        }
    });
});

I know the e.name isn't right, but there must be someway to do something similar to that, no?

And I'm using IE9 and above.

Thief answered 2/10, 2014 at 14:20 Comment(2)
You should bind click events on submit buttons instead of form submit eventDolli
@ApulGupta - Ok, but why? Obviously, I have a misunderstanding about how the submit function and event argument work. So an explanation of why I need to do this with click instead of submit is better much than a directive. If you don't want to bother with that, fine. But I'm just putting it out there for answerers in general.Thief
A
0

You can maintain the form, just add additional events to setup which button called the submit.

var form_config = {button: null};

$("#submit1").click(function(){
  form_config.button = 'submit1';  
});

$("#submit2").click(function(){
  form_config.button = 'submit2';  
});

$('#testform').submit(function(e) {
    console.log(e);
    e.preventDefault();

    var submiturl;

    if (form_config.button === 'submit1') { submiturl = '../sendToFactory.cshtml'; }
    else if (form_config.button  === 'submit2') { submiturl = '../sendOverseas.cshtml'; }
    $("#hi").val(submiturl);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form id="testform">
    <input type="text" id="hi" name="hi" />
    <input type="text" id="bye" name="bye" />

    <button type="submit" id="submit1">Use Me</button>
    <button type="submit" id="submit2">No, Use Me </button>
</form>
Accentuate answered 2/10, 2014 at 14:42 Comment(9)
So basically there's no way for the e argument to know which button was clicked. Is that what it comes down to?Thief
well, the event target will always be the form, as that's what the event is hooked up to.Accentuate
This code is screaming for an error to occur. I would never use this. And why are you creating a global variable with an object with only 1 value? Why don't you just throw the value of the submiturl in the if inside the submit handler? And for this to be minimally usable, you must wrap it up in a function.Levasseur
the reason for the object is because I would assume the complexity of what he wants to do could be variable, he can setup different attributes and whatever, it's good design practice to utilize encapsulated data with readable and understandable coding conventions. "form_config" is the configuration for the form, it's rather simple really, you're upset because I didn't make it for this one use case only? I find your criticism invalid.Accentuate
Nobody thinks that this is funny answer? why should we bind form submit event if this can be done only using click events of submit buttons? @Accentuate any reason why you are just doing such kind of tweaks?Dolli
@Accentuate if his code was supposed to be more complex, you really think that a sparse global object declared somewhere will help to ease the trouble?Levasseur
@IsmaelMiguel I'm not sure why you keep bringing up that it's global, are you so afraid of global objects that you refrain from using them at all? This kind of thinking is not logical, it's pseudo-logical thinking that all global objects are inherently bad. If the form is the main function of the page, then it makes complete sense that the form configuration object would be global to the page that contains the form. I'm not sure where you learned about your coding practices but it seems to me like you've got a very conservative viewpoint as to coding practices that frankly in js is antiquatedAccentuate
@Accentuate My coding practices were self-acquired. You are incorrect about my views regarding global objects. In my opinion, they should be avoided. But there are situations when the best to do is to use global objects (which I consider risky). This is not the situation. In fact, this can be done without resorting to global or local variables! And besides, with your code, there is a bigged chance of a XSS attack succeeding, redirecting the call to another page and no one would even know.Levasseur
The way he has decided to go about doing this, having it all client side, any point of saying that "your code is unsafe" is a moot point, obviously we could take a lot of this code server side and benefit from the security that would provide, but this is stackoverflow, we're answering peoples questions, sure we could berate him for using client side authentication of forms, but who cares, if this was something he needs to be secure, he wouldn't be doing it in Javascript. You really need to take a step back and realize that not everything needs to be secure.Accentuate
Z
2

You can turn "type='submit'" to "type='button'" so it does not submit form and listen to the buttons clicks:

$("#testform button[type=button]").click(function (e) {
    var submitUrl;
    switch ($(e.target).attr('id')) {
        case 'submit1':
            submitUrl = 'url1.cshtml';
            break;
        case 'submit2':
            submitUrl = 'url2.cshtml';
            break;
    }

    $.ajax({
                //...
    })
});
Zapateado answered 2/10, 2014 at 14:27 Comment(4)
Why are you doing $(e.target).attr('id') when you can do e.target.id? Why are you calling jQuery just to get the id? An event handler should just do its thing and move away. Calling jQuery is a lot slower. (just to be safe, using my example, you should use (e.target||{id:''}).id) and it would still outperform jQuery)Levasseur
@IsmaelMiguel, you are right, but speaking for myself, I don't care about that 0.001% performance increase. Also, jQuery takes care of cross-browser compatibility. As far as every browser supports "e.target.id" syntax, your solution will work. But IF, some, let's say 1337 version of IE, changes that for some reason, It won't.Zapateado
Well, IE is a cancer, but if e.target.id breaks, then ALL objects won't work. For example: document.getElementsByTagName('body')[0].style.backgroundColor would break too. This will render most of the existing libraries and websites useless.Levasseur
You are right. It's just my personal style. In most cases, I do much more complex logic inside click event listener, than just taking .id, that is why my reflexes are "I want jQuery from target first".Zapateado
P
2

You can extract the info from new FormData(form) while handling the submit event where form is a reference to <form> element. Note that you have to extract the info while handling the event because even if you go through event loop (e.g. setTimeout(..., 0)) the submit button info has already been lost.

It turns out that latest browsers do not populate FormData with the submit button anymore. So nowadays you can do something like following, given reference to <form> element as form:

form.addEventListener('submit', function(event)
{
    event.preventDefault();
    var formdata = new FormData(form);
    formdata.append(event.submitter.name, event.submitter.value);
    ...
    xhr.send(formdata);
}

The event.submitter will contain a reference to the form button that submitted the form.

In case the form may have multiple submit event handlers and one or more of those may actually modify the data on the form before submitting it (e.g. TinyMCE) you may need to do tricks like

form.addEventListener('submit', function(event)
{
    let form = this;
    let submitter = event.submitter;
    setTimeout(function()
    {
        let formdata = new FormData(form);
        formdata.append(submitter.name, submitter.value);
        xhr.send(formdata);
    }, 0);
    event.preventDefault();
}

The setTimeout(..., 0) will allow all existing submit handlers to run and the full event loop to drain empty before proceeding to collect the FormData and send the XHR.

Poeticize answered 16/11, 2020 at 12:20 Comment(0)
H
0

If you don't use the submit event of the form and you need to use the button event trigger then you should do something like this :

$('button').click(function(e){
var id$ = $(this).attr('id');
e.preventdefault();

var submiturl;

if (id$ == 'submit1') { submiturl = '../sendToFactory.cshtml'; }
else if (id$ == 'submit2') { submiturl = '../sendOverseas.cshtml'; }

$.ajax({
    url: submiturl,
    data: $('testform').serialize(),
    type: 'POST',
    datatype: 'json',
    success: function (response) {
        //stuff
    },
    error: function (response) {
        //error
    }
    });
});
Hardshell answered 2/10, 2014 at 14:28 Comment(4)
Where did you got $this from? And why are you creating a global variable named id$?Levasseur
$this is a jquery object made from the click event. About the global variable I write this code pretty quick as a exemple not as a gooduse code you obviously should do var id$ = ... NOTE : $this is the jquery element of the clicked button.Hardshell
Uncaught exception: ReferenceError: Undefined variable: $this using jQuery 1.11.0 on Opera 12.17 on Windows XP SP3 x86.Levasseur
My bad sorry you should use $(this); I really write this code to quick. SorryHardshell
A
0

You can maintain the form, just add additional events to setup which button called the submit.

var form_config = {button: null};

$("#submit1").click(function(){
  form_config.button = 'submit1';  
});

$("#submit2").click(function(){
  form_config.button = 'submit2';  
});

$('#testform').submit(function(e) {
    console.log(e);
    e.preventDefault();

    var submiturl;

    if (form_config.button === 'submit1') { submiturl = '../sendToFactory.cshtml'; }
    else if (form_config.button  === 'submit2') { submiturl = '../sendOverseas.cshtml'; }
    $("#hi").val(submiturl);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form id="testform">
    <input type="text" id="hi" name="hi" />
    <input type="text" id="bye" name="bye" />

    <button type="submit" id="submit1">Use Me</button>
    <button type="submit" id="submit2">No, Use Me </button>
</form>
Accentuate answered 2/10, 2014 at 14:42 Comment(9)
So basically there's no way for the e argument to know which button was clicked. Is that what it comes down to?Thief
well, the event target will always be the form, as that's what the event is hooked up to.Accentuate
This code is screaming for an error to occur. I would never use this. And why are you creating a global variable with an object with only 1 value? Why don't you just throw the value of the submiturl in the if inside the submit handler? And for this to be minimally usable, you must wrap it up in a function.Levasseur
the reason for the object is because I would assume the complexity of what he wants to do could be variable, he can setup different attributes and whatever, it's good design practice to utilize encapsulated data with readable and understandable coding conventions. "form_config" is the configuration for the form, it's rather simple really, you're upset because I didn't make it for this one use case only? I find your criticism invalid.Accentuate
Nobody thinks that this is funny answer? why should we bind form submit event if this can be done only using click events of submit buttons? @Accentuate any reason why you are just doing such kind of tweaks?Dolli
@Accentuate if his code was supposed to be more complex, you really think that a sparse global object declared somewhere will help to ease the trouble?Levasseur
@IsmaelMiguel I'm not sure why you keep bringing up that it's global, are you so afraid of global objects that you refrain from using them at all? This kind of thinking is not logical, it's pseudo-logical thinking that all global objects are inherently bad. If the form is the main function of the page, then it makes complete sense that the form configuration object would be global to the page that contains the form. I'm not sure where you learned about your coding practices but it seems to me like you've got a very conservative viewpoint as to coding practices that frankly in js is antiquatedAccentuate
@Accentuate My coding practices were self-acquired. You are incorrect about my views regarding global objects. In my opinion, they should be avoided. But there are situations when the best to do is to use global objects (which I consider risky). This is not the situation. In fact, this can be done without resorting to global or local variables! And besides, with your code, there is a bigged chance of a XSS attack succeeding, redirecting the call to another page and no one would even know.Levasseur
The way he has decided to go about doing this, having it all client side, any point of saying that "your code is unsafe" is a moot point, obviously we could take a lot of this code server side and benefit from the security that would provide, but this is stackoverflow, we're answering peoples questions, sure we could berate him for using client side authentication of forms, but who cares, if this was something he needs to be secure, he wouldn't be doing it in Javascript. You really need to take a step back and realize that not everything needs to be secure.Accentuate
A
0

try this

$(document).ready(function() {
    $( "form" ).submit(function () {
        // Get the submit button element
        var btn = $(this).find("button:focus").val();
        alert(btn);
        //DO YOUR AJAX
    });
});
Akanke answered 2/10, 2014 at 15:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.