Rails UJS will use the window.confirm() if you want to confirm a link click. It allows you to customize this to use a library like Bootstrap, Noty or your own. The problem is customizing doesn’t work. It doesn’t work because it expects your custom to return ‘true’ or ‘false,’ just like window.confirm() does. Your custom method, however, does not block the browser, like window.confirm() does, nor can it, so the call to your custom method returns without waiting for user input.
The simplest way I found to customize the Rails UJS confirmation process and make it work asynchronously, is to override $.rails.allowAction. The idea is to display confirmation dialog and add callback to the OK button click event. That callback will remove the data-confirm attribute from the link which will essentially make it non-confirmable (if you could click on it again, it would be executed without any confirmation). So all you need really is to trigger the ‘ click’ event again on that link (the actual name of the event is ‘ click.rails’) and close the confirmation dialog.
Here’s the overridden implementation of the allowAction and callback we’ll add for the click on the OK button on the confirmation dialog. You also need to pick one of the implementations of the showConfirmDialog below, depending on the library you’re using.
$.rails.allowAction = (link) ->
return true unless link.attr('data-confirm')
$.rails.showConfirmDialog(link) # look bellow for implementations
false # always stops the action since code runs asynchronously
$.rails.confirmed = (link) ->
link.removeAttr('data-confirm')
link.trigger('click.rails')
$.rails.showConfirmDialog = (link) ->
message = link.attr 'data-confirm'
html = """
<div class="modal" id="confirmationDialog">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>#{message}</h3>
</div>
<div class="modal-body">
<p>Are you sure you want to delete?</p>
</div>
<div class="modal-footer">
<a data-dismiss="modal" class="btn">Cancel</a>
<a data-dismiss="modal" class="btn btn-primary confirm">OK</a>
</div>
</div>
"""
$(html).modal()
$('#confirmationDialog .confirm').on 'click', -> $.rails.confirmed(link)
$.rails.showConfirmDialog = (link) ->
html = """
<div id="dialog-confirm" title="Are you sure you want to delete?">
<p>These item will be permanently deleted and cannot be recovered. Are you sure?</p>
</div>
"""
$(html).dialog
resizable: false
modal: true
buttons:
OK: ->
$.rails.confirmed link
$(this).dialog "close"
Cancel: ->
$(this).dialog "close"
$.rails.showConfirmDialog = (link) ->
okButton =
type: 'btn btn-primary'
text: 'Ok'
click: (noty) -> $.rails.confirmed(link); noty.close()
cancelButton =
type: 'btn btn-danger'
text: 'Cancel'
click: (noty) -> noty.close()
noty
text: link.attr('data-confirm')
buttons: [okButton, cancelButton]
closable: false
timeout: false
modal: true
A nice follow up article by PJ McCormick.
If you wanted it to build a product you’d find a way to get time to work on it. If you really wanted to start that new hobby you’d sacrifice something to find the time and money to do it.
I'll define a "Wannabe Entrepreneur" as someone who has never made money from their businesses. Here are the different types of wannabes.
In the past few years I've built go-carts, built a 200+ sq ft workshop, written several eBooks. How do I create a life where I have time to work on side projects?
Receive 5 Software projects mistakes we have made over the years and how to avoid them.