Button Behavior Inside a Form

A form is usually associated with a submit button. In Rails, you typically have a form specified as following: (if use form_for helper)

<%= form_for(@meeting) do |f| %>
  <%= render "shared/error", :target => @meeting %>

  <div class="panel panel-default">
    <div class="panel-heading">     
      <h3 class="panel-title">Basic info</h3>
    </div>
    <div class="panel-body">
      <div class="form-group">
        <%= f.label :title %>
        <%= f.text_field :title, id:"title" %>
      </div>
      <div class="form-group">
        <%= f.label :description %>
        <%= f.text_field :description %>
      </div>      
    </div>
  </div >
<%= f.submit class: "btn btn-large btn-primary" %>
<% end %>

On this particular page, I have another field that requires user's input to insert into the form. Let's say a user could manually insert meeting location options. Each time a user types in a location in an input box, he presses "Add Location" button and JQuery injects that element into the page. Before the submit button is clicked, the user can have a good look at all the options that he inputs on the page. Submit button at the end will submit the form. We insert this piece of markup in the form_for block, right before submit button defined.

<div class="field" id="location">
  
  <label for="location">Enter new location option(s):</label>
  <button class="text form-control" type="text" name="rtt" id="trest"></button>
  
  <input class="button restb btn btn-default" name="morerest" type="button" value="Add location"></input>     
</div>

Associated Javascript code:

<script>
$(".restb").click(function() {
  var ivalue = $("#trest")
  var rvalue = ivalue.val();
  $('table.rest').append("<div align='right'>"+rvalue+"<input name='locationname[]' type='hidden' id='addedrest' value='"+rvalue+"'></input></div>");
  ivalue.val("");
})
</script>

It all looks fine. When I click on the "Add location" button, it triggered JQuery script and did inject the input text on the page. But then immediately after that, it submitted the form automatically. The submit button at bottom didn't even get touched. Why?

In order to simplify the issue, I reduced the code downto bare minimum and see what caused the problem.

<%= form_for(@meeting) do |f| %>  
  <button class="button restb btn btn-default" name="morerest" value="Add location"></button>

  <%= f.submit class: "btn btn-large btn-primary" %>
<% end %>

Yes, it did that again! I then replaced the button element with an input element but with type="button" attribute specified.

<input class="button restb btn btn-default" name="morerest" type="button" value="Add location"></input>

That solved the problem! So the culprit lies in the button element inside a form. The real reason is:

If the button is within a form, the default behavior is submit.

If the button is not within a form, it will do nothing.

That's why! Because we didn't specify the type of button, it defaults to submit. After executes JQuery script, it automatically submits the form.

But that's not all.

Always specify the type attribute for the button. The default type for Internet Explorer is "button", while in other browsers (and in the W3C specification) it is "submit".

Detailed document on button element in form can be found here.