Skip to content

Commit

Permalink
Make disable_with default in submit_tag
Browse files Browse the repository at this point in the history
Prevents double submission by making disable_with the default.
As far as I understand it there shouldn't be very man downsides
from this and this would help ensure good default behavior.

Default disable_with option will only be applied if user has not
specified her/his own disable_with option, whether that is in the
`data-disable-with` string form or the
`:data => { :disable_with => "Saving..." }` hash form. disable_with
will default to the value attribute.
  • Loading branch information
DropsOfSerenity committed Aug 8, 2015
1 parent 57989c5 commit 7467fda
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 20 deletions.
5 changes: 5 additions & 0 deletions actionview/CHANGELOG.md
@@ -1,3 +1,8 @@
* Make `disable_with` the default behavior for submit tags. Disables the
button on submit to prevent double submits.

*Justin Schiff*

* Add wildcard matching to explicit dependencies.

Turns:
Expand Down
33 changes: 23 additions & 10 deletions actionview/lib/action_view/helpers/form_tag_helper.rb
Expand Up @@ -412,36 +412,49 @@ def radio_button_tag(name, value, checked = false, options = {})
# * <tt>confirm: 'question?'</tt> - If present the unobtrusive JavaScript
# drivers will provide a prompt with the question specified. If the user accepts,
# the form is processed normally, otherwise no action is taken.
# * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
# * <tt>:disable_with</tt> - Defaults to value attribute. Value of this parameter will be used as the value for a
# disabled version of the submit button when the form is submitted. This feature is
# provided by the unobtrusive JavaScript driver.
# provided by the unobtrusive JavaScript driver. To disable this feature for a single submit tag
# pass :data => { :disable_with => false }
#
# ==== Examples
# submit_tag
# # => <input name="commit" type="submit" value="Save changes" />
# # => <input name="commit" data-disable-with="Save changes" type="submit" value="Save changes" />
#
# submit_tag "Edit this article"
# # => <input name="commit" type="submit" value="Edit this article" />
# # => <input name="commit" data-disable-with="Edit this article" type="submit" value="Edit this article" />
#
# submit_tag "Save edits", disabled: true
# # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
# # => <input disabled="disabled" name="commit" data-disable-with="Save edits" type="submit" value="Save edits" />
#
# submit_tag "Complete sale", data: { disable_with: "Please wait..." }
# # => <input name="commit" data-disable-with="Please wait..." type="submit" value="Complete sale" />
# submit_tag "Complete sale", data: { disable_with: "Submitting..." }
# # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />
#
# submit_tag nil, class: "form_submit"
# # => <input class="form_submit" name="commit" type="submit" />
#
# submit_tag "Edit", class: "edit_button"
# # => <input class="edit_button" name="commit" type="submit" value="Edit" />
# # => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
#
# submit_tag "Save", data: { confirm: "Are you sure?" }
# # => <input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />
# # => <input name='commit' type='submit' value='Save' data-disable-with="Save" data-confirm="Are you sure?" />
#
def submit_tag(value = "Save changes", options = {})
options = options.stringify_keys
tag_options = { "type" => "submit", "name" => "commit", "value" => value }.update(options)

tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options)
disable_with_text = value.clone
disable_with_text = tag_options["data"][:disable_with] if tag_options["data"] && tag_options["data"].has_key?(:disable_with)
disable_with_text = tag_options["data-disable-with"] if tag_options.has_key?("data-disable-with")

if disable_with_text
tag_options.deep_merge!({ "data" => { "disable_with" => disable_with_text } })
else
tag_options.extract!("data-disable-with")
tag_options["data"].extract!(:disable_with) if tag_options["data"]
end

tag :input, tag_options
end

# Creates a button element that defines a <tt>submit</tt> button,
Expand Down
18 changes: 9 additions & 9 deletions actionview/test/template/form_helper_test.rb
Expand Up @@ -1577,7 +1577,7 @@ def test_form_for
"<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" +
"<input name='post[secret]' type='hidden' value='0' />" +
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
"<input name='commit' type='submit' value='Create post' />" +
"<input name='commit' data-disable-with='Create post' type='submit' value='Create post' />" +
"<button name='button' type='submit'>Create post</button>" +
"<button name='button' type='submit'><span>Create post</span></button>"
end
Expand Down Expand Up @@ -1854,7 +1854,7 @@ def test_form_for_with_model_using_relative_model_naming

expected = whole_form("/posts/44", "edit_post_44", "edit_post", method: "patch") do
"<input name='post[title]' type='text' id='post_title' value='And his name will be forty and four.' />" +
"<input name='commit' type='submit' value='Edit post' />"
"<input name='commit' data-disable-with='Edit post' type='submit' value='Edit post' />"
end

assert_dom_equal expected, output_buffer
Expand All @@ -1875,7 +1875,7 @@ def test_form_for_with_symbol_object_name
"<textarea name='other_name[body]' id='other_name_body'>\nBack to the hill and over it again!</textarea>" +
"<input name='other_name[secret]' value='0' type='hidden' />" +
"<input name='other_name[secret]' checked='checked' id='other_name_secret' value='1' type='checkbox' />" +
"<input name='commit' value='Create post' type='submit' />"
"<input name='commit' value='Create post' data-disable-with='Create post' type='submit' />"
end

assert_dom_equal expected, output_buffer
Expand Down Expand Up @@ -2083,7 +2083,7 @@ def test_form_for_label_error_wrapping
expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', method: 'patch') do
"<div class='field_with_errors'><label for='post_author_name' class='label'>Author name</label></div>" +
"<div class='field_with_errors'><input name='post[author_name]' type='text' id='post_author_name' value='' /></div>" +
"<input name='commit' type='submit' value='Create post' />"
"<input name='commit' data-disable-with='Create post' type='submit' value='Create post' />"
end

assert_dom_equal expected, output_buffer
Expand All @@ -2101,7 +2101,7 @@ def test_form_for_label_error_wrapping_without_conventional_instance_variable
expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', method: 'patch') do
"<div class='field_with_errors'><label for='post_author_name' class='label'>Author name</label></div>" +
"<div class='field_with_errors'><input name='post[author_name]' type='text' id='post_author_name' value='' /></div>" +
"<input name='commit' type='submit' value='Create post' />"
"<input name='commit' data-disable-with='Create post' type='submit' value='Create post' />"
end

assert_dom_equal expected, output_buffer
Expand Down Expand Up @@ -2226,7 +2226,7 @@ def test_submit_with_object_as_new_record_and_locale_strings
end

expected = whole_form('/posts', 'new_post', 'new_post') do
"<input name='commit' type='submit' value='Create Post' />"
"<input name='commit' data-disable-with='Create Post' type='submit' value='Create Post' />"
end

assert_dom_equal expected, output_buffer
Expand All @@ -2240,7 +2240,7 @@ def test_submit_with_object_as_existing_record_and_locale_strings
end

expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', method: 'patch') do
"<input name='commit' type='submit' value='Confirm Post changes' />"
"<input name='commit' data-disable-with='Confirm Post changes' type='submit' value='Confirm Post changes' />"
end

assert_dom_equal expected, output_buffer
Expand All @@ -2254,7 +2254,7 @@ def test_submit_without_object_and_locale_strings
end

expected = whole_form do
"<input name='commit' class='extra' type='submit' value='Save changes' />"
"<input name='commit' class='extra' data-disable-with='Save changes' type='submit' value='Save changes' />"
end

assert_dom_equal expected, output_buffer
Expand All @@ -2268,7 +2268,7 @@ def test_submit_with_object_and_nested_lookup
end

expected = whole_form('/posts/123', 'edit_another_post', 'edit_another_post', method: 'patch') do
"<input name='commit' type='submit' value='Update your Post' />"
"<input name='commit' data-disable-with='Update your Post' type='submit' value='Update your Post' />"
end

assert_dom_equal expected, output_buffer
Expand Down
31 changes: 30 additions & 1 deletion actionview/test/template/form_tag_helper_test.rb
Expand Up @@ -426,13 +426,42 @@ def test_stringify_symbol_keys
assert_dom_equal expected, actual
end


def test_submit_tag
assert_dom_equal(
%(<input name='commit' data-disable-with="Saving..." onclick="alert(&#39;hello!&#39;)" type="submit" value="Save" />),
submit_tag("Save", :onclick => "alert('hello!')", :data => { :disable_with => "Saving..." })
)
end

def test_empty_submit_tag
assert_dom_equal(
%(<input data-disable-with="Save" name='commit' type="submit" value="Save" />),
submit_tag("Save")
)
end

def test_data_disable_with_string
assert_dom_equal(
%(<input data-disable-with="Processing..." data-confirm="Are you sure?" name='commit' type="submit" value="Save" />),
submit_tag("Save", { "data-disable-with" => "Processing...", "data-confirm" => "Are you sure?" })
)
end

def test_data_disable_with_boolean
assert_dom_equal(
%(<input data-confirm="Are you sure?" name='commit' type="submit" value="Save" />),
submit_tag("Save", { "data-disable-with" => false, "data-confirm" => "Are you sure?" })
)
end

def test_data_hash_disable_with_boolean
assert_dom_equal(
%(<input data-confirm="Are you sure?" name='commit' type="submit" value="Save" />),
submit_tag("Save", { :data => { :confirm => "Are you sure?", :disable_with => false } })
)
end

def test_submit_tag_with_no_onclick_options
assert_dom_equal(
%(<input name='commit' data-disable-with="Saving..." type="submit" value="Save" />),
Expand All @@ -442,7 +471,7 @@ def test_submit_tag_with_no_onclick_options

def test_submit_tag_with_confirmation
assert_dom_equal(
%(<input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />),
%(<input name='commit' type='submit' value='Save' data-confirm="Are you sure?" data-disable-with="Save" />),
submit_tag("Save", :data => { :confirm => "Are you sure?" })
)
end
Expand Down

0 comments on commit 7467fda

Please sign in to comment.