Every Rails developers might be already familiar with data-confirmattribute for a link. It is used to ask for user confirmation before executing the action on behalf of user. Here is one example
<%= link_to 'Destroy', product,
:confirm => '删除后无法恢复,你确定删除吗?',
:method => :delete %>
The generated link looks like this:
<a href="/products/4" data-confirm="删除后无法恢复,你确定删除吗?"
data-method="delete" rel="nofollow">Destroy</a>
When users click on this link, they will see a confirmation dialog to ask them if they are sure to delete that post. Some developers will wonder how it is implemented on Rails, right? Actually, there is no magic in it. If you look at application.js
file in your Rails app, you will mostly see the following line
//= require jquery_ujs
Some developers look at it too quickly and they thought that is jQuery UI library. NO, it is not. This is jquery-ujs (https://github.com/rails/jquery-ujs) and it allows Rails to handle links with custom data-
attributes such as data-method
or data-confirm
. More specifically, it will handle the click events on any links have these attributes and prevent the default action if necessary. You can take a look at this file if you are interested in understanding the logic behind it, https://github.com/rails/jquery-ujs/blob/master/src/rails.js
One thing I don't like about data-confirm
is that it uses Javascript confirm
method, with the default confirmation dialog of the browsers. There are many fancy and beautiful dialogs out there for us to use, and I think it would be much better if we can integrate them into our application instead of using the default one. For example, take a look at two favorite libraries which I like to use: Bootbox, SweetAlert
In order to do this, we will need to override the event handler of jquery-ujs
and handle the event on our own. I created a JS script for doing this (I actually took the idea from a guy on the Internet or Stackoverflow but I forgot the link to that post). You can just copy this script and put this in your application.js.
//Override the default confirm dialog by rails $.rails.allowAction = function(link){ if (link.data("confirm") == undefined){ return true; } $.rails.showConfirmationDialog(link); return false; } //User click confirm button $.rails.confirmed = function(link){ link.data("confirm", null); link.trigger("click.rails"); } //Display the confirmation dialog $.rails.showConfirmationDialog = function(link){ var message = link.data("confirm"); $("#dialog-confirm").dialog({ resizable: false, height: "auto", width: 400, modal: true, buttons: { "确定": function() { $(this).dialog("close"); $.rails.confirmed(link); }, "取消": function() { $(this).dialog("close"); } } }); $("#dialog-confirm-content").html(message); $("#dialog-confirm").dialog("open"); }
Explanation
We first override allowAction
method with our own method. This is the method called by jquery-ujs when user clicks on a link with data-
attributes. If the link does not contain "data-confirm" attribute, we will just return and let users execute the action as normal. Otherwise, we show the confirmation dialog.
//Override the default confirm dialog by rails $.rails.allowAction = function(link){ if (link.data("confirm") == undefined){ return true; } $.rails.showConfirmationDialog(link); return false; }
Next, we handle the case in which user clicks on the Confirm button
//User click confirm button $.rails.confirmed = function(link){ link.data("confirm", null); link.trigger("click.rails"); }
Notice that we set data-confirm
attribute to null to avoid recursive loop and then trigger click.rails
event to let the default event handler to execute the action
Finally, we handle the function to show the dialog to users.
//Display the confirmation dialog $.rails.showConfirmationDialog = function(link){ var message = link.data("confirm"); $("#dialog-confirm").dialog({ resizable: false, height: "auto", width: 400, modal: true, buttons: { "确定": function() { $(this).dialog("close"); $.rails.confirmed(link); }, "取消": function() { $(this).dialog("close"); } } }); $("#dialog-confirm-content").html(message); $("#dialog-confirm").dialog("open"); }
In the above script, I use JqueryUI modal-confirmation plugin . If you want to use another library, just replace the code starting with$("#dialog-confirm")
with your own modal. You would need to pay attention to the logic of handling Confirm and Cancel button to make it work properly although it is pretty straightforward.
/project/app/views/layouts/application.html.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Depot</title>
<%= stylesheet_link_tag "application","depot","scaffold","jquery-ui-1.12.1-css/jquery-ui", :media => "all" %>
<%= javascript_include_tag "application","jquery","jquery-ui-1.12.1-js/jquery-ui" %>
<%= csrf_meta_tags %>
</head>
<body id="store">
<div id="banner">
<%= image_tag( "logo.png" ) %>
<%= @page_title || "Pragmatic Bookshelf" %>
</div>
<div id="columns">
<div id="side">
</div>
<div id="main">
<%= yield %>
</div>
</div>
</body>
<div id="dialog-confirm" title="确认对话框" style="display:none;">
<div id="confirm-imgs"><img src="/assets/tips.png" ></div>
<div id="dialog-confirm-content">These items will be permanently deleted and cannot be recovered. Are you sure?</div>
</div>
</html>
css
#dialog-confirm #confirm-imgs{
display: inline-block;
vertical-align: middle;
}
#dialog-confirm #confirm-imgs img{
width:60px;
height:60px;
}
#dialog-confirm #dialog-confirm-content{
display: inline-block;
}
#dialog-confirm-content {
font-size:16px;
}
That's it. Let's forget boring confirm window and start using your beautiful modal.
http://stackoverflow.com/questions/7435859/custom-rails-confirm-box-with-rails-confirm-override
http://lesseverything.com/blog/customizing-confirmation-dialog-in-rails/#