Which submit button did I click?


#1

How can I found out which submit button was clicked in a form with 2 submit buttons?

App.html

  <form class="authenticate">
    Username: <input type="text" name="username"/> <br>
    Password: <input type="text" name="password"/> <br>
              <input type="submit" class="create" value="Create" name="Create"/>
              <input type="submit" class="login"  value="Login"  name="Login" />
  </form>

App.js

"submit .authenticate": function (event) {           

  //Prevent page refresh.
  event.preventDefault();     
  
  //Log.
  console.log("create");
  console.log(event);
  
  //Authenticate
  var username = event.target.username.value;
  var password = event.target.password.value;
  Accounts.createUser( {username:username, password:password} );     

  //Prevent page refresh.
  event.preventDefault();
  
},

#2

#3

Am I supposed to write a separate application to be able to determine which submit button was clicked?
Which of these 20 solutions is the correct one?
These solutions have nothing to do with Meteor?
Info that I need is not part of Meteor event parameter?
If so why not?
These examples are in jQuery which I don’t know.
Once inside event handler I also need access to all the form fields.
Can I get info on generated HTTP request?


#4

Instead of using the submit event, you could add a click event handler for each button.
You question is not meteor specific. The event handlers you write in meteor actually use jquery.

    "click .authenticate input[value=submit]": function(e, t){
        //code for submit
    }

     "click .authenticate input[value=login]": function(e, t){
         //code for login
     }

You can get values of input fields through jquery

var username = t.$("form.authenticate input[name=username]").val();

#5

Am I supposed to write a separate application to be able to determine which submit button was clicked?

Javascript is a language that is best utilized when broken into functions and each function can in fact serve as an app that does one unit of job. Programming is all about solving problems of doing units of work.

Which of these 20 solutions is the correct one?

Correct answers are marked as correct with the green checkmark. Furthermore, other high quality answers have higher rankings which are displayed in the form of number of upvotes right beside the question.

These solutions have nothing to do with Meteor?

Meteor is not a dom event handler. It is a platform, or arguably a framework. It allows you to write otherwise verbose code in concise units. The template event handlers are very powerful in that regard. Meteor allows you to utilize any javascript solution to a unit of problem in a straightforward manner.

Info that I need is not part of Meteor event parameter?

No. It is not a limitation imposed by Meteor. It is how dom, events and javascript works. The proposed solutions are not very elegant, but they are not ugly hacks either.

If so why not?

Meteor is not a magic wand. But it is one of the six cool vendors pointed out by Gartner. Gartner is the most serious assessor of trends and technologies out there. You will be much happier if you appreciate what you already have and make full use of it. Regardless of the fact, your problem is irrelevant to Meteor and is already provided with a solution that is applicable to your meteor app.

These examples are in jQuery which I don’t know.

You should take a couple of hours of break from your work and read/watch a jquery tutorial. It is extremely easy to learn and very powerful. It will save you many hours of effort with dom handling.

Once inside event handler I also need access to all the form fields.

Meteor docs for event maps is very easy to follow and has some examples. Template.find is your friend. So is jquery.

Can I get info on generated HTTP request?

There is no HTTP request. Meteor does not work in a request/response manner. It is explained at the very beginning of the docs. Furthermore, you are already stopping any http request yourself by doing event.preventDefault() which you should.


I also suggest you to refactor your code to not use multiple submit buttons and a single event handler. Your apps two different buttons do two distinct things so they should have two distinct events and associated handlers. They may share some common code (tasks) but that’s what javascript functions are all about.

I’ll also take my chances here and suggest you to be more involved with and appreciative of what you’ve got (meteor) and who you deal with (people who help you without waiting something in return). If you have actually read meteor docs and the link that sashko has shared with you, you would have solved your problem by now. But I sincerely hope that this answer puts you on the right track.


#6

@nlammertyn
I tried using on click events for buttons but in that case I don’t get the form into the event and therefore I can’t access username and password fields.

I have experimented a bit and decided for this solution. I don’t think it was suggested in proposed link but it is possible that I didn’t understand all of the proposed solutions. If this solution is OK but it is not proposed then I wonder if maybe there is something wrong with it. My main criteria is to have simplest possible solution.

App.html

  <form class="authenticate">
    Username: <input type="text" name="username"/> <br>
    Password: <input type="text" name="password" /> <br>
              <input type="submit" value="Create" onclick="this.parentNode.value='create';" />
              <input type="submit" value="Login"  onclick="this.parentNode.value='login'; " />
  </form>

App.js

"submit .authenticate": function (event) {           

  //Prevent page refresh.
  event.preventDefault();

  //Authenticate
  var username = event.target.username.value;
  var password = event.target.password.value;
        
  //Action.
  var action = event.target.value;
  if (action == 'create') {
    console.log('crete');
    Accounts.createUser( {username:username, password:password} );    
  }
  else if (action == 'login') {
    console.log('login');
    Meteor.loginWithPassword(username, password);
  }       
  
},

#7

@nlammertyn’s solution is better. Your solution has some problems:

  • the user can submit by hitting the enter/return key, so your onclick hacks would not work
  • the submit and onclick event handlers may not always complete in an order you expect so event.target.value can be undefined
  • two submit buttons and a value on form element are bad dom practice

#8

@serkandurusoy

  1. If I press enter this behaves as if I have clicked on Create
  2. This I didn’t know. Could be a problem.
  3. Alternative is to have
  • two sets of username/password fields which clutters the page or
  • to have two pages which complicates the code
  • and if instead of username and password I have fields for two numbers and different buttons representing different mathematical operations then I don’t think there is a way around it.

@nlammertyn
So once I am inside the event after clicking on a button I can still access every element on the template/page and therefore I could still access username and password fields. Didn’t know that. I will try that to.


#9

@ivoronline If this works for you then go for it! It’s all about discovering things for yourself, that’s how you learn best.

Anyway here’s a full snippet of how I’d do it:

  "click .authenticate input[value=submit]": function(e, t){
       var username = t.$("form.authenticate input[name=username]").val();
       var password = t.$("form.authenticate input[name=password]").val();
       Accounts.createUser({username:username, password:password});  
   }

 "click .authenticate input[value=login]": function(e, t){
       var username = t.$("form.authenticate input[name=username]").val();
       var password = t.$("form.authenticate input[name=password]").val();
       Meteor.loginWithPassword(username, password);  
  }

(don’t copy paste, this was written by heart and may contain syntax mistakes)


#10

@nlammertyn
Thank you very much for taking time to write complete example.
I don’t know JQuery but I think I understand your point.
I promise I will try to learn JQuery as soon as I finish learning Meteor basics.
I will try to test your solution in JavaScript.

@serkandurusoy
And I apologize if I have sound rude.
My experience so far with this forum was super great and I appreciate all the help I could get.
sashko has already helped me a lot and we had some little discussions so I have only respect for him. So far I didn’t have any problems here so I wasn’t really focused on how my questions might look like. I will try to be more careful next time.


#11

@ivoronline You can still use your own code as you created already… just add a little trick.
I just tested and verified… the below solution should work fine.

'submit form.authenticate': function (event) {
  event.preventDefault();
  var btn = $(event.target).find("input[type=submit]:focus");
  if (btn) {
    if (btn[0].className === 'create') {
      console.log('create user');
    } else if (btn[0].className === 'login') {
      console.log('login user');
    }
  }
}

cheers!


#12

@anbuselvan
This solution would be great since it doesn’t require adding code to HTML but it doesn’t work when you press enter while editing input fields since input field has focus then.

Maybe pressing enter to submit should be disabled somehow although I personally like it since it makes logging in easier.


#13

@ivoronline I’m glad you found the right solution. :thumbsup:


#14

Or simply if no button has focus then default action should be performed.
I think this could be the simplest solution.
Thank you very much.
I only hope I can write this in JavaScript somehow.


#15

Cool… I’m trying to figure out how we can extend this solution when pressing from input field. I’ll post it later as I make progress. I believe it should be an easy fix as well.


#16

And if you could write it in JavaScript please.


#17

it’s there already…

'submit form.authenticate': function (event) {
  event.preventDefault();
  var btn = $(event.target).find("input[type=submit]:focus");
  if (btn) {
    if (btn[0].className === 'create') {
      console.log('create user');
    } else if (btn[0].className === 'login') {
      console.log('login user');
    }
  } else {
    console.log('default action');
  }
}

#18

Oh yeah. It works. I put else on wrong place.


#19

you can also write it more specific so that you can understand it easily…

  if (btn === undefined) {
    console.log('default action');
  } else {
    if (btn[0].className === 'create') {
      console.log('create user');
    } else if (btn[0].className === 'login') {
      console.log('login user');
    }
  }

#20

if (btn.length != 0)
if (btn[0] !== undefined)

  //Get action.
  var action = 'create';
  var button = $(event.target).find("input[type=submit]:focus");
  if (button[0] !== undefined) { action = button[0].className; }

  //Perform action.
  if (action == 'create') {
    console.log('create');
    Accounts.createUser( {username:username, password:password} );
  }
  else if (action == 'login') {
    console.log('login');
    Meteor.loginWithPassword(username, password);
  }