296
votes

I have an HTML table of rows tied to database rows. I'd like to have a "delete row" link for each row, but I would like to confirm with the user beforehand.

Is there any way to do this using the Twitter Bootstrap modal dialog?

12
Having run across this question I wanted to chime-in with (what seems to me) such a simple and more streamlined "fix" for this issue. I struggled with it for a while and then realized how simple it can be: just put the actual form submission button in the modal dialog, and then the submit button on the form itself does nothing but fire the dialog window... problem solved.Michael Doleman
@jonijones this example is not working for me (the confirmation message doesn't display upon click of the first button) - tested in chromeegmfrs

12 Answers

415
votes

GET recipe

For this task you can use already available plugins and bootstrap extensions. Or you can make your own confirmation popup with just 3 lines of code. Check it out.

Say we have this links (note data-href instead of href) or buttons that we want to have delete confirmation for:

<a href="#" data-href="delete.php?id=23" data-toggle="modal" data-target="#confirm-delete">Delete record #23</a>

<button class="btn btn-default" data-href="/delete.php?id=54" data-toggle="modal" data-target="#confirm-delete">
    Delete record #54
</button>

Here #confirm-delete points to a modal popup div in your HTML. It should have an "OK" button configured like this:

<div class="modal fade" id="confirm-delete" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                ...
            </div>
            <div class="modal-body">
                ...
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                <a class="btn btn-danger btn-ok">Delete</a>
            </div>
        </div>
    </div>
</div>

Now you only need this little javascript to make a delete action confirmable:

$('#confirm-delete').on('show.bs.modal', function(e) {
    $(this).find('.btn-ok').attr('href', $(e.relatedTarget).data('href'));
});

So on show.bs.modal event delete button href is set to URL with corresponding record id.

Demo: http://plnkr.co/edit/NePR0BQf3VmKtuMmhVR7?p=preview


POST recipe

I realize that in some cases there might be needed to perform POST or DELETE request rather then GET. It it still pretty simple without too much code. Take a look at the demo below with this approach:

// Bind click to OK button within popup
$('#confirm-delete').on('click', '.btn-ok', function(e) {

  var $modalDiv = $(e.delegateTarget);
  var id = $(this).data('recordId');

  $modalDiv.addClass('loading');
  $.post('/api/record/' + id).then(function() {
     $modalDiv.modal('hide').removeClass('loading');
  });
});

// Bind to modal opening to set necessary data properties to be used to make request
$('#confirm-delete').on('show.bs.modal', function(e) {
  var data = $(e.relatedTarget).data();
  $('.title', this).text(data.recordTitle);
  $('.btn-ok', this).data('recordId', data.recordId);
});

// Bind click to OK button within popup
$('#confirm-delete').on('click', '.btn-ok', function(e) {

  var $modalDiv = $(e.delegateTarget);
  var id = $(this).data('recordId');

  $modalDiv.addClass('loading');
  setTimeout(function() {
    $modalDiv.modal('hide').removeClass('loading');
  }, 1000);

  // In reality would be something like this
  // $modalDiv.addClass('loading');
  // $.post('/api/record/' + id).then(function() {
  //   $modalDiv.modal('hide').removeClass('loading');
  // });
});

// Bind to modal opening to set necessary data properties to be used to make request
$('#confirm-delete').on('show.bs.modal', function(e) {
  var data = $(e.relatedTarget).data();
  $('.title', this).text(data.recordTitle);
  $('.btn-ok', this).data('recordId', data.recordId);
});
.modal.loading .modal-content:before {
  content: 'Loading...';
  text-align: center;
  line-height: 155px;
  font-size: 20px;
  background: rgba(0, 0, 0, .8);
  position: absolute;
  top: 55px;
  bottom: 0;
  left: 0;
  right: 0;
  color: #EEE;
  z-index: 1000;
}
<script data-require="jquery@*" data-semver="2.0.3" src="//code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="bootstrap@*" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link data-require="[email protected]" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />

<div class="modal fade" id="confirm-delete" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
        <h4 class="modal-title" id="myModalLabel">Confirm Delete</h4>
      </div>
      <div class="modal-body">
        <p>You are about to delete <b><i class="title"></i></b> record, this procedure is irreversible.</p>
        <p>Do you want to proceed?</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-danger btn-ok">Delete</button>
      </div>
    </div>
  </div>
</div>
<a href="#" data-record-id="23" data-record-title="The first one" data-toggle="modal" data-target="#confirm-delete">
        Delete "The first one", #23
    </a>
<br />
<button class="btn btn-default" data-record-id="54" data-record-title="Something cool" data-toggle="modal" data-target="#confirm-delete">
  Delete "Something cool", #54
</button>

Demo: http://plnkr.co/edit/V4GUuSueuuxiGr4L9LmG?p=preview


Bootstrap 2.3

Here is an original version of the code I made when I was answering this question for Bootstrap 2.3 modal.

$('#modal').on('show', function() {
    var id = $(this).data('id'),
        removeBtn = $(this).find('.danger');
    removeBtn.attr('href', removeBtn.attr('href').replace(/(&|\?)ref=\d*/, '$1ref=' + id));
});

Demo: http://jsfiddle.net/MjmVr/1595/

162
votes

http://bootboxjs.com/ - latest works with Bootstrap 3.0.0

The simplest possible example:

bootbox.alert("Hello world!"); 

From the site:

The library exposes three methods designed to mimic their native JavaScript equivalents. Their exact method signatures are flexible as each can take various parameters to customise labels and specify defaults, but they are most commonly called like so:

bootbox.alert(message, callback)
bootbox.prompt(message, callback)
bootbox.confirm(message, callback)

Here's a snippet of it in action (click "Run code snippet" below):

$(function() {
  bootbox.alert("Hello world!");
});
<!-- required includes -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/>

<!-- bootbox.js at 4.4.0 -->
<script src="https://rawgit.com/makeusabrew/bootbox/f3a04a57877cab071738de558581fbc91812dce9/bootbox.js"></script>
31
votes
  // ---------------------------------------------------------- Generic Confirm  

  function confirm(heading, question, cancelButtonTxt, okButtonTxt, callback) {

    var confirmModal = 
      $('<div class="modal hide fade">' +    
          '<div class="modal-header">' +
            '<a class="close" data-dismiss="modal" >&times;</a>' +
            '<h3>' + heading +'</h3>' +
          '</div>' +

          '<div class="modal-body">' +
            '<p>' + question + '</p>' +
          '</div>' +

          '<div class="modal-footer">' +
            '<a href="#" class="btn" data-dismiss="modal">' + 
              cancelButtonTxt + 
            '</a>' +
            '<a href="#" id="okButton" class="btn btn-primary">' + 
              okButtonTxt + 
            '</a>' +
          '</div>' +
        '</div>');

    confirmModal.find('#okButton').click(function(event) {
      callback();
      confirmModal.modal('hide');
    });

    confirmModal.modal('show');     
  };

  // ---------------------------------------------------------- Confirm Put To Use

  $("i#deleteTransaction").live("click", function(event) {
    // get txn id from current table row
    var id = $(this).data('id');

    var heading = 'Confirm Transaction Delete';
    var question = 'Please confirm that you wish to delete transaction ' + id + '.';
    var cancelButtonTxt = 'Cancel';
    var okButtonTxt = 'Confirm';

    var callback = function() {
      alert('delete confirmed ' + id);
    };

    confirm(heading, question, cancelButtonTxt, okButtonTxt, callback);

  });
29
votes

I'd realise its a very old question, but since i wondered today for a more efficient method of handling the bootstrap modals. I did some research and found something better then the solutions which are shown above, that can be found at this link:

http://www.petefreitag.com/item/809.cfm

First load the jquery

$(document).ready(function() {
    $('a[data-confirm]').click(function(ev) {
        var href = $(this).attr('href');

        if (!$('#dataConfirmModal').length) {
            $('body').append('<div id="dataConfirmModal" class="modal" role="dialog" aria-labelledby="dataConfirmLabel" aria-hidden="true"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button><h3 id="dataConfirmLabel">Please Confirm</h3></div><div class="modal-body"></div><div class="modal-footer"><button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button><a class="btn btn-primary" id="dataConfirmOK">OK</a></div></div>');
        } 
        $('#dataConfirmModal').find('.modal-body').text($(this).attr('data-confirm'));
        $('#dataConfirmOK').attr('href', href);
        $('#dataConfirmModal').modal({show:true});
        return false;
    });
});

Then just ask any question/confirmation to href:

<a href="/any/url/delete.php?ref=ID" data-confirm="Are you sure you want to delete?">Delete</a>

This way the confirmation modal is a lot more universal and so it can easily be re-used on other parts of your website.

18
votes

Thanks to @Jousby's solution, I managed to get mine working as well, but found I had to improve his solution's Bootstrap modal markup a bit to make it render correctly as demonstrated in the official examples.

So, here's my modified version of the generic confirm function that worked fine:

/* Generic Confirm func */
  function confirm(heading, question, cancelButtonTxt, okButtonTxt, callback) {

    var confirmModal = 
      $('<div class="modal fade">' +        
          '<div class="modal-dialog">' +
          '<div class="modal-content">' +
          '<div class="modal-header">' +
            '<a class="close" data-dismiss="modal" >&times;</a>' +
            '<h3>' + heading +'</h3>' +
          '</div>' +

          '<div class="modal-body">' +
            '<p>' + question + '</p>' +
          '</div>' +

          '<div class="modal-footer">' +
            '<a href="#!" class="btn" data-dismiss="modal">' + 
              cancelButtonTxt + 
            '</a>' +
            '<a href="#!" id="okButton" class="btn btn-primary">' + 
              okButtonTxt + 
            '</a>' +
          '</div>' +
          '</div>' +
          '</div>' +
        '</div>');

    confirmModal.find('#okButton').click(function(event) {
      callback();
      confirmModal.modal('hide');
    }); 

    confirmModal.modal('show');    
  };  
/* END Generic Confirm func */
10
votes

I found this useful and easy to use, plus it looks pretty: http://maxailloud.github.io/confirm-bootstrap/.

To use it, include the .js file in your page then run:

$('your-link-selector').confirmModal();

There are various options you can apply to it, to make it look better when doing it to confirm a delete, I use:

$('your-link-selector').confirmModal({
    confirmTitle: 'Please confirm',
    confirmMessage: 'Are you sure you want to delete this?',
    confirmStyle: 'danger',
    confirmOk: '<i class="icon-trash icon-white"></i> Delete',
    confirmCallback: function (target) {
         //perform the deletion here, or leave this option
         //out to just follow link..
    }
});
4
votes

I can easily handle this type of task using bootbox.js library. At first you need to include bootbox JS file. Then in your event handler function simply write following code:

    bootbox.confirm("Are you sure to want to delete , function(result) {

    //here result will be true
    // delete process code goes here

    });

Offical bootboxjs site

2
votes

Following solution is better than bootbox.js, because

  • It can do everything bootbox.js can do;
  • The use syntax is simpler
  • It allows you to elegantly control the color of your message using "error", "warning" or "info"
  • Bootbox is 986 lines long, mine only 110 lines long

digimango.messagebox.js:

const dialogTemplate = '\
    <div class ="modal" id="digimango_messageBox" role="dialog">\
        <div class ="modal-dialog">\
            <div class ="modal-content">\
                <div class ="modal-body">\
                    <p class ="text-success" id="digimango_messageBoxMessage">Some text in the modal.</p>\
                    <p><textarea id="digimango_messageBoxTextArea" cols="70" rows="5"></textarea></p>\
                </div>\
                <div class ="modal-footer">\
                    <button type="button" class ="btn btn-primary" id="digimango_messageBoxOkButton">OK</button>\
                    <button type="button" class ="btn btn-default" data-dismiss="modal" id="digimango_messageBoxCancelButton">Cancel</button>\
                </div>\
            </div>\
        </div>\
    </div>';


// See the comment inside function digimango_onOkClick(event) {
var digimango_numOfDialogsOpened = 0;


function messageBox(msg, significance, options, actionConfirmedCallback) {
    if ($('#digimango_MessageBoxContainer').length == 0) {
        var iDiv = document.createElement('div');
        iDiv.id = 'digimango_MessageBoxContainer';
        document.getElementsByTagName('body')[0].appendChild(iDiv);
        $("#digimango_MessageBoxContainer").html(dialogTemplate);
    }

    var okButtonName, cancelButtonName, showTextBox, textBoxDefaultText;

    if (options == null) {
        okButtonName = 'OK';
        cancelButtonName = null;
        showTextBox = null;
        textBoxDefaultText = null;
    } else {
        okButtonName = options.okButtonName;
        cancelButtonName = options.cancelButtonName;
        showTextBox = options.showTextBox;
        textBoxDefaultText = options.textBoxDefaultText;
    }

    if (showTextBox == true) {
        if (textBoxDefaultText == null)
            $('#digimango_messageBoxTextArea').val('');
        else
            $('#digimango_messageBoxTextArea').val(textBoxDefaultText);

        $('#digimango_messageBoxTextArea').show();
    }
    else
        $('#digimango_messageBoxTextArea').hide();

    if (okButtonName != null)
        $('#digimango_messageBoxOkButton').html(okButtonName);
    else
        $('#digimango_messageBoxOkButton').html('OK');

    if (cancelButtonName == null)
        $('#digimango_messageBoxCancelButton').hide();
    else {
        $('#digimango_messageBoxCancelButton').show();
        $('#digimango_messageBoxCancelButton').html(cancelButtonName);
    }

    $('#digimango_messageBoxOkButton').unbind('click');
    $('#digimango_messageBoxOkButton').on('click', { callback: actionConfirmedCallback }, digimango_onOkClick);

    $('#digimango_messageBoxCancelButton').unbind('click');
    $('#digimango_messageBoxCancelButton').on('click', digimango_onCancelClick);

    var content = $("#digimango_messageBoxMessage");

    if (significance == 'error')
        content.attr('class', 'text-danger');
    else if (significance == 'warning')
        content.attr('class', 'text-warning');
    else
        content.attr('class', 'text-success');

    content.html(msg);

    if (digimango_numOfDialogsOpened == 0)
        $("#digimango_messageBox").modal();

    digimango_numOfDialogsOpened++;
}

function digimango_onOkClick(event) {
    // JavaScript's nature is unblocking. So the function call in the following line will not block,
    // thus the last line of this function, which is to hide the dialog, is executed before user
    // clicks the "OK" button on the second dialog shown in the callback. Therefore we need to count
    // how many dialogs is currently showing. If we know there is still a dialog being shown, we do
    // not execute the last line in this function.
    if (typeof (event.data.callback) != 'undefined')
        event.data.callback($('#digimango_messageBoxTextArea').val());

    digimango_numOfDialogsOpened--;

    if (digimango_numOfDialogsOpened == 0)
        $('#digimango_messageBox').modal('hide');
}

function digimango_onCancelClick() {
    digimango_numOfDialogsOpened--;

    if (digimango_numOfDialogsOpened == 0)
        $('#digimango_messageBox').modal('hide');
}

To use digimango.messagebox.js:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>A useful generic message box</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />

    <link rel="stylesheet" type="text/css" href="~/Content/bootstrap.min.css" media="screen" />
    <script src="~/Scripts/jquery-1.10.2.min.js" type="text/javascript"></script>
    <script src="~/Scripts/bootstrap.js" type="text/javascript"></script>
    <script src="~/Scripts/bootbox.js" type="text/javascript"></script>

    <script src="~/Scripts/digimango.messagebox.js" type="text/javascript"></script>


    <script type="text/javascript">
        function testAlert() {
            messageBox('Something went wrong!', 'error');
        }

        function testAlertWithCallback() {
            messageBox('Something went wrong!', 'error', null, function () {
                messageBox('OK clicked.');
            });
        }

        function testConfirm() {
            messageBox('Do you want to proceed?', 'warning', { okButtonName: 'Yes', cancelButtonName: 'No' }, function () {
                messageBox('Are you sure you want to proceed?', 'warning', { okButtonName: 'Yes', cancelButtonName: 'No' });
            });
        }

        function testPrompt() {
            messageBox('How do you feel now?', 'normal', { showTextBox: true }, function (userInput) {
                messageBox('User entered "' + userInput + '".');
            });
        }

        function testPromptWithDefault() {
            messageBox('How do you feel now?', 'normal', { showTextBox: true, textBoxDefaultText: 'I am good!' }, function (userInput) {
                messageBox('User entered "' + userInput + '".');
            });
        }

    </script>
</head>

<body>
    <a href="#" onclick="testAlert();">Test alert</a> <br/>
    <a href="#" onclick="testAlertWithCallback();">Test alert with callback</a> <br />
    <a href="#" onclick="testConfirm();">Test confirm</a> <br/>
    <a href="#" onclick="testPrompt();">Test prompt</a><br />
    <a href="#" onclick="testPromptWithDefault();">Test prompt with default text</a> <br />
</body>

</html>
enter image description here
1
votes

When its comes to a relevantly big project we may need something re-usable. This is something I came with with help of SO.

confirmDelete.jsp

<!-- Modal Dialog -->
<div class="modal fade" id="confirmDelete" role="dialog" aria-labelledby="confirmDeleteLabel"
 aria-hidden="true">
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal"
                    aria-hidden="true">&times;</button>
            <h4 class="modal-title">Delete Parmanently</h4>
        </div>
        <div class="modal-body" style="height: 75px">
            <p>Are you sure about this ?</p>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
            <button type="button" class="btn btn-danger" id="confirm-delete-ok">Ok
            </button>
        </div>
    </div>
</div>

<script type="text/javascript">

    var url_for_deletion = "#";
    var success_redirect = window.location.href;

$('#confirmDelete').on('show.bs.modal', function (e) {
    var message = $(e.relatedTarget).attr('data-message');
    $(this).find('.modal-body p').text(message);
    var title = $(e.relatedTarget).attr('data-title');
    $(this).find('.modal-title').text(title);

    if (typeof  $(e.relatedTarget).attr('data-url') != 'undefined') {
        url_for_deletion = $(e.relatedTarget).attr('data-url');
    }
    if (typeof  $(e.relatedTarget).attr('data-success-url') != 'undefined') {
        success_redirect = $(e.relatedTarget).attr('data-success-url');
    }

});

<!-- Form confirm (yes/ok) handler, submits form -->
$('#confirmDelete').find('.modal-footer #confirm-delete-ok').on('click', function () {
    $.ajax({
        method: "delete",
        url: url_for_deletion,
    }).success(function (data) {
        window.location.href = success_redirect;
    }).fail(function (error) {
        console.log(error);
    });
    $('#confirmDelete').modal('hide');
    return false;
});
<script/>

reusingPage.jsp

<a href="#" class="table-link danger"
data-toggle="modal"
data-target="#confirmDelete"
data-title="Delete Something"
data-message="Are you sure you want to inactivate this something?"
data-url="client/32"
id="delete-client-32">
</a>
<!-- jQuery should come before this -->
<%@ include file="../some/path/confirmDelete.jsp" %>

Note: This uses http delete method for delete request, you can change it from javascript or, can send it using a data-attribute as in data-title or data-url etc, for support any request.

1
votes

If you want to do it in the easiest shortcut, then u can do it with this plugin.


But this plugin is an alternate implementation using Bootstrap Modal. And real Bootstrap implementation is also very easy, so I don't like to use this plugin because it adds excess JS contents in the page, which will slow down the page loading time.


Idea

I like to implement it by myself by this way-

  1. If user clicks on a button to delete an item from the list, then a JS call will put Item ID (or any more essential data) in a form in the modal.
  2. Then in the pop-up, there will be 2 buttons for confirmation.

    • Yes will submit the form (with ajax or direct form submit)
    • No will just dismiss the modal

The code will be like this (using Bootstrap)-

<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
  <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<script>
$(document).ready(function()
{
    $("button").click(function()
    {
        //Say - $('p').get(0).id - this delete item id
        $("#delete_item_id").val( $('p').get(0).id );
        $('#delete_confirmation_modal').modal('show');
    });
});
</script>

<p id="1">This is a item to delete.</p>

<button type="button" class="btn btn-danger">Delete</button>

<!-- Delete Modal content-->

<div class="modal fade" id="delete_confirmation_modal" role="dialog" style="display: none;">
	<div class="modal-dialog" style="margin-top: 260.5px;">
				<div class="modal-content">
			<div class="modal-header">
				<button type="button" class="close" data-dismiss="modal">×</button>
				<h4 class="modal-title">Do you really want to delete this Category?</h4>
			</div>
			<form role="form" method="post" action="category_delete" id="delete_data">
				<input type="hidden" id="delete_item_id" name="id" value="12">
				<div class="modal-footer">
					<button type="submit" class="btn btn-danger">Yes</button>
					<button type="button" class="btn btn-primary" data-dismiss="modal">No</button>
				</div>
			</form>
		</div>

	</div>
</div>

You should change the form action according to your requirement.

Happy coading :)

1
votes

You can try more reusable my solution with callback function. In this function you can use POST request or some logic. Used libraries: JQuery 3> and Bootstrap 3>.

https://jsfiddle.net/axnikitenko/gazbyv8v/

Html code for test:

...
<body>
    <a href='#' id="remove-btn-a-id" class="btn btn-default">Test Remove Action</a>
</body>
...

Javascript:

$(function () {
    function remove() {
        alert('Remove Action Start!');
    }
    // Example of initializing component data
    this.cmpModalRemove = new ModalConfirmationComponent('remove-data', remove,
        'remove-btn-a-id', {
            txtModalHeader: 'Header Text For Remove', txtModalBody: 'Body For Text Remove',
            txtBtnConfirm: 'Confirm', txtBtnCancel: 'Cancel'
        });
    this.cmpModalRemove.initialize();
});

//----------------------------------------------------------------------------------------------------------------------
// COMPONENT SCRIPT
//----------------------------------------------------------------------------------------------------------------------
/**
 * Script processing data for confirmation dialog.
 * Used libraries: JQuery 3> and Bootstrap 3>.
 *
 * @param name unique component name at page scope
 * @param callback function which processing confirm click
 * @param actionBtnId button for open modal dialog
 * @param text localization data, structure:
 *              > txtModalHeader - text at header of modal dialog
 *              > txtModalBody - text at body of modal dialog
 *              > txtBtnConfirm - text at button for confirm action
 *              > txtBtnCancel - text at button for cancel action
 *
 * @constructor
 * @author Aleksey Nikitenko
 */
function ModalConfirmationComponent(name, callback, actionBtnId, text) {
    this.name = name;
    this.callback = callback;
    // Text data
    this.txtModalHeader =   text.txtModalHeader;
    this.txtModalBody =     text.txtModalBody;
    this.txtBtnConfirm =    text.txtBtnConfirm;
    this.txtBtnCancel =     text.txtBtnCancel;
    // Elements
    this.elmActionBtn = $('#' + actionBtnId);
    this.elmModalDiv = undefined;
    this.elmConfirmBtn = undefined;
}

/**
 * Initialize needed data for current component object.
 * Generate html code and assign actions for needed UI
 * elements.
 */
ModalConfirmationComponent.prototype.initialize = function () {
    // Generate modal html and assign with action button
    $('body').append(this.getHtmlModal());
    this.elmActionBtn.attr('data-toggle', 'modal');
    this.elmActionBtn.attr('data-target', '#'+this.getModalDivId());
    // Initialize needed elements
    this.elmModalDiv =  $('#'+this.getModalDivId());
    this.elmConfirmBtn = $('#'+this.getConfirmBtnId());
    // Assign click function for confirm button
    var object = this;
    this.elmConfirmBtn.click(function() {
        object.elmModalDiv.modal('toggle'); // hide modal
        object.callback(); // run callback function
    });
};

//----------------------------------------------------------------------------------------------------------------------
// HTML GENERATORS
//----------------------------------------------------------------------------------------------------------------------
/**
 * Methods needed for get html code of modal div.
 *
 * @returns {string} html code
 */
ModalConfirmationComponent.prototype.getHtmlModal = function () {
    var result = '<div class="modal fade" id="' + this.getModalDivId() + '"';
    result +=' tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">';
    result += '<div class="modal-dialog"><div class="modal-content"><div class="modal-header">';
    result += this.txtModalHeader + '</div><div class="modal-body">' + this.txtModalBody + '</div>';
    result += '<div class="modal-footer">';
    result += '<button type="button" class="btn btn-default" data-dismiss="modal">';
    result += this.txtBtnCancel + '</button>';
    result += '<button id="'+this.getConfirmBtnId()+'" type="button" class="btn btn-danger">';
    result += this.txtBtnConfirm + '</button>';
    return result+'</div></div></div></div>';
};

//----------------------------------------------------------------------------------------------------------------------
// UTILITY
//----------------------------------------------------------------------------------------------------------------------
/**
 * Get id element with name prefix for this component.
 *
 * @returns {string} element id
 */
ModalConfirmationComponent.prototype.getModalDivId = function () {
    return this.name + '-modal-id';
};

/**
 * Get id element with name prefix for this component.
 *
 * @returns {string} element id
 */
ModalConfirmationComponent.prototype.getConfirmBtnId = function () {
    return this.name + '-confirm-btn-id';
};
1
votes

POST Recipe with navigation to target page and reusable Blade file

dfsq's answer is very nice. I modified it a bit to fit my needs: I actually needed a modal for the case that, after clicking, the user would also be navigated to the corresponding page. Executing the query asynchronously is not always what one needs.

Using Blade I created the file resources/views/includes/confirmation_modal.blade.php:

<div class="modal fade" id="confirmation-modal" tabindex="-1" role="dialog" aria-labelledby="confirmation-modal-label" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h4>{{ $headerText }}</h4>
            </div>
            <div class="modal-body">
                {{ $bodyText }}
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                <form action="" method="POST" style="display:inline">
                    {{ method_field($verb) }}
                    {{ csrf_field() }}
                    <input type="submit" class="btn btn-danger btn-ok" value="{{ $confirmButtonText }}" />
                </form>
            </div>
        </div>
    </div>
</div>

<script>
    $('#confirmation-modal').on('show.bs.modal', function(e) {
        href = $(e.relatedTarget).data('href');

        // change href of button to corresponding target
        $(this).find('form').attr('action', href);
    });
</script>

Now, using it is straight-forward:

<a data-href="{{ route('data.destroy', ['id' => $data->id]) }}" data-toggle="modal" data-target="#confirmation-modal" class="btn btn-sm btn-danger">Remove</a>

Not much changed here and the modal can be included like this:

@include('includes.confirmation_modal', ['headerText' => 'Delete Data?', 'bodyText' => 'Do you really want to delete these data? This operation is irreversible.',
'confirmButtonText' => 'Remove Data', 'verb' => 'DELETE'])

Just by putting the verb in there, it uses it. This way, CSRF is also utilized.

Helped me, maybe it helps someone else.