Disable buttons in table actions when pressed
By default, Rails disables submit inputs (<input type="submit">) when they're pressed so we avoid a double-submission when users click the button twice. However, Rails does not disable submit buttons (<button type="submit">) when they're pressed. This means there's a chance users might press the button several times. Even if most our table actions are idempotent, it might cause certain issues. For instance, pressing the "Delete" button twice means the second request might raise an `ActiveRecord::RecordNotFound` exception. Disabling the button also gives feedback to users, letting them know they've correctly clicked the button.
This commit is contained in:
6
app/assets/stylesheets/admin/action.scss
Normal file
6
app/assets/stylesheets/admin/action.scss
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
.admin .admin-action {
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
@include button-disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<% if options[:method] && options[:method] != :get %>
|
<% if button? %>
|
||||||
<%= button_to(path, html_options) { text } %>
|
<%= button_to(path, html_options) { text } %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= link_to text, path, html_options %>
|
<%= link_to text, path, html_options %>
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ class Admin::ActionComponent < ApplicationComponent
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def button?
|
||||||
|
options[:method] && options[:method] != :get
|
||||||
|
end
|
||||||
|
|
||||||
def text
|
def text
|
||||||
options[:text] || t("admin.actions.#{action}")
|
options[:text] || t("admin.actions.#{action}")
|
||||||
end
|
end
|
||||||
@@ -22,12 +26,15 @@ class Admin::ActionComponent < ApplicationComponent
|
|||||||
{
|
{
|
||||||
class: html_class,
|
class: html_class,
|
||||||
"aria-label": label,
|
"aria-label": label,
|
||||||
data: { confirm: confirmation_text }
|
data: {
|
||||||
}.merge(options.except(:"aria-label", :confirm, :path, :text))
|
confirm: confirmation_text,
|
||||||
|
disable_with: (text if button?)
|
||||||
|
}
|
||||||
|
}.merge(options.except(:"aria-label", :class, :confirm, :path, :text))
|
||||||
end
|
end
|
||||||
|
|
||||||
def html_class
|
def html_class
|
||||||
"#{action.to_s.gsub("_", "-")}-link"
|
"admin-action #{options[:class] || "#{action.to_s.gsub("_", "-")}-link"}".strip
|
||||||
end
|
end
|
||||||
|
|
||||||
def label
|
def label
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
require "rails_helper"
|
require "rails_helper"
|
||||||
|
|
||||||
describe Admin::ActionComponent do
|
describe Admin::ActionComponent do
|
||||||
it "includes an HTML class for the action" do
|
describe "HTML class" do
|
||||||
|
it "includes an HTML class for the action by default" do
|
||||||
render_inline Admin::ActionComponent.new(:edit, double, path: "/")
|
render_inline Admin::ActionComponent.new(:edit, double, path: "/")
|
||||||
|
|
||||||
expect(page).to have_css "a.edit-link"
|
expect(page).to have_css "a.edit-link.admin-action"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "keeps the admin-action class when the class is overwritten" do
|
||||||
|
render_inline Admin::ActionComponent.new(:edit, double, path: "/", class: "modify-link")
|
||||||
|
|
||||||
|
expect(page).to have_css "a.modify-link.admin-action"
|
||||||
|
expect(page).not_to have_css ".edit-link"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "aria-label attribute" do
|
describe "aria-label attribute" do
|
||||||
@@ -105,4 +114,18 @@ describe Admin::ActionComponent do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "data-disable-with attribute" do
|
||||||
|
it "is not rendered for links" do
|
||||||
|
render_inline Admin::ActionComponent.new(:edit, double, path: "/")
|
||||||
|
|
||||||
|
expect(page).not_to have_css "[data-disable-with]"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is rendered for buttons" do
|
||||||
|
render_inline Admin::ActionComponent.new(:hide, double, path: "/", method: :delete)
|
||||||
|
|
||||||
|
expect(page).to have_css "button[data-disable-with='Hide']"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user