83

I'm developing an ASP.Net MVC site and on it I list some bookings from a database query in a table with an ActionLink to cancel the booking on a specific row with a certain BookingId like this:

My bookings

<table cellspacing="3">
    <thead>
        <tr style="font-weight: bold;">
            <td>Date</td>
            <td>Time</td>
            <td>Seats</td>      
            <td></td>              
            <td></td>
        </tr>
    </thead>            
    <tr>
        <td style="width: 120px;">2008-12-27</td>
        <td style="width: 120px;">13:00 - 14:00</td>
        <td style="width: 100px;">2</td>
        <td style="width: 60px;"><a href="/Booking.aspx/Cancel/15">cancel</a></td>
        <td style="width: 80px;"><a href="/Booking.aspx/Change/15">change</a></td>
    </tr>            
    <tr>
        <td style="width: 120px;">2008-12-27</td>
        <td style="width: 120px;">15:00 - 16:00</td>
        <td style="width: 100px;">3</td>
        <td style="width: 60px;"><a href="/Booking.aspx/Cancel/10">cancel</a></td>
        <td style="width: 80px;"><a href="/Booking.aspx/Change/10">change</a></td>
    </tr>  
</table>

What would be nice is if I could use the jQuery Dialog to popup a message asking if the user is sure he wants to cancel the booking. I have been trying get this to work but I keep getting stuck on how to create a jQuery function that accepts parameters so that I can replace the

<a href="/Booking.aspx/Cancel/10">cancel</a>

with

<a href="#" onclick="ShowDialog(10)">cancel</a>.

The ShowDialog function would then open the dialog and also pass the paramter 10 to the dialog so that if the user clicks yes then It will post the href: /Booking.aspx/Change/10

I have created the jQuery Dialog in a script like this:

$(function() {
    $("#dialog").dialog({
        autoOpen: false,
        buttons: {
            "Yes": function() {
                alert("a Post to :/Booking.aspx/Cancel/10 would be so nice here instead of the alert");},
            "No": function() {$(this).dialog("close");}
        },
        modal: true,
        overlay: {
            opacity: 0.5,
            background: "black"
        }
    });
});   

and the dialog itself:

   <div id="dialog" title="Cancel booking">Are you sure you want to cancel your booking?</div>

So finally to my question: How can I accomplish this? or is there a better way of doing it?

Rahul Gupta
  • 9,775
  • 7
  • 56
  • 69
Frederik
  • 2,178
  • 4
  • 20
  • 20

11 Answers11

275

jQuery provides a method which store data for you, no need to use a dummy attribute or to find workaround to your problem.

Bind the click event:

$('a[href*=/Booking.aspx/Change]').bind('click', function(e) {
    e.preventDefault();
    $("#dialog-confirm")
        .data('link', this)  // The important part .data() method
        .dialog('open');
});

And your dialog:

$("#dialog-confirm").dialog({
    autoOpen: false,
    resizable: false,
    height:200,
    modal: true,
    buttons: {
        Cancel: function() {
            $(this).dialog('close');
        },
        'Delete': function() {
            $(this).dialog('close');
            var path = $(this).data('link').href; // Get the stored result
            $(location).attr('href', path);
        }
    }
});
Boris Guéry
  • 47,316
  • 8
  • 52
  • 87
  • 16
    This is a brilliant solution. I was not aware that you could set data on a dialog using .data I have been setting global variables for ages, accessing them from my dialogs and then destroying them! – Kevin Bradshaw Feb 22 '11 at 17:47
  • Thank you very much for this .data() magic. Notice the folowing update though: "As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document" http://api.jquery.com/bind/ – daniloquio Feb 13 '12 at 14:21
  • 2
    The .data parameter is definately the way to go. Thanks! – Andreas May 02 '12 at 01:50
  • 1
    +1 I've searched the jquery ui documentation and couldn't find this until I realised this was a method from jQuery core itself. Very nice catch – Tivie Feb 05 '13 at 07:01
  • @boris-guery Hi, I tried it, but didn't manage to make it work. It just doesn't prevent the default action, so it goes to the link instead of opening the dialog. Any help would be appreciated: I make a jsfiddle: http://jsfiddle.net/sebababi/9zKcZ/ – Sebastian Dec 17 '13 at 18:52
  • @Sebastian, looks like you've to wrap your attribute value with quote: http://jsfiddle.net/96TK7/2/ btw, you should not use `.bind` anymore which has been deprecated but `.on` instead, check the jQuery documentation. – Boris Guéry Dec 17 '13 at 22:31
  • @boris-guery, thanks Boris, I saw your fiddle, but it doesn't seem to work for me. I don't even get the 'here' alert to pop. I changed the bind to on. http://jsfiddle.net/96TK7/3/ I even tried with jQuery 2.0.2. Does it open the dialog box and the alert at your end? thanks. – Sebastian Dec 18 '13 at 12:23
  • @Sebastian, well that's weird, I properly get the alert, and it seems correct to me. However, I advise you to post a new question on the subject if you've difficulties to set this up. – Boris Guéry Dec 18 '13 at 12:41
  • @Frodo The `.data()` method is part of jQuery itself, not jQuery UI: https://api.jquery.com/data/ – Bpainter Dec 10 '15 at 18:22
45

You could do it like this:

  • mark the <a> with a class, say "cancel"
  • set up the dialog by acting on all elements with class="cancel":

    $('a.cancel').click(function() { 
      var a = this; 
      $('#myDialog').dialog({
        buttons: {
          "Yes": function() {
             window.location = a.href; 
          }
        }
      }); 
      return false;
    });
    

(plus your other options)

The key points here are:

  • make it as unobtrusive as possible
  • if all you need is the URL, you already have it in the href.

However, I recommend that you make this a POST instead of a GET, since a cancel action has side effects and thus doesn't comply with GET semantics...

Mauricio Scheffer
  • 98,863
  • 23
  • 192
  • 275
  • Thanx for a good answer. I'm will try it out, one question though. you mention that it's better to make it a POST instead of a GET which implies that a regular href like href="/Booking.aspx/Cancel/10" would be a GET ist that right? and if so what would it lool like to make it a post then? – Frederik Dec 27 '08 at 09:59
  • In order to make it a post, instead of changing the window.location, you could use jQuery $.post() ajax function. See http://docs.jquery.com/Ajax/jQuery.post#examples – Franck Dec 27 '08 at 12:57
  • 1
    I wouldn't use $.post(), that approach doesn't degrade well. Just write a standard
    without any ajax, make it work without confirmation, and *then* add the confirmation "on top" of your
    – Mauricio Scheffer Dec 28 '08 at 14:23
  • This is also known as the hijax approach (http://domscripting.com/blog/display/41) – Mauricio Scheffer Dec 28 '08 at 14:25
  • You don't *have* to use post, but if you use a get for a database-altering operation, you open yourself to a "cross-site request forgery" attack...see: https://en.wikipedia.org/wiki/Cross-site_request_forgery – strickli Aug 31 '15 at 16:08
2

In terms of what you are doing with jQuery, my understanding is that you can chain functions like you have and the inner ones have access to variables from the outer ones. So is your ShowDialog(x) function contains these other functions, you can re-use the x variable within them and it will be taken as a reference to the parameter from the outer function.

I agree with mausch, you should really look at using POST for these actions, which will add a <form> tag around each element, but make the chances of an automated script or tool triggering the Cancel event much less likely. The Change action can remain as is because it (presumably just opens an edit form).

Falkayn
  • 559
  • 3
  • 15
1

After SEVERAL HOURS of try/catch I finally came with this working example, its working on AJAX POST with new rows appends to the TABLE on the fly (that was my real problem):

Tha magic came with link this:

<a href="#" onclick="removecompany(this);return false;" id="remove_13">remove</a>
<a href="#" onclick="removecompany(this);return false;" id="remove_14">remove</a>
<a href="#" onclick="removecompany(this);return false;" id="remove_15">remove</a>

This is the final working with AJAX POST and Jquery Dialog:

  <script type= "text/javascript">/*<![CDATA[*/
    var $k = jQuery.noConflict();  //this is for NO-CONFLICT with scriptaculous
     function removecompany(link){
        companyid = link.id.replace('remove_', '');
    $k("#removedialog").dialog({
                bgiframe: true,
                resizable: false,
                height:140,
                autoOpen:false,
                modal: true,
                overlay: {
                    backgroundColor: '#000',
                    opacity: 0.5
                },
                buttons: {
                    'Are you sure ?': function() {
                        $k(this).dialog('close');
                        alert(companyid);
                        $k.ajax({
                              type: "post",
                              url: "../ra/removecompany.php",
                              dataType: "json",
                              data: {
                                    'companyid' : companyid
                                    },
                              success: function(data) {
                                    //alert(data);
                                    if(data.success)
                                    {
                                        //alert('success'); 
                                        $k('#companynew'+companyid).remove();
                                    }
                          }
                        }); // End ajax method
                    },
                    Cancel: function() {
                        $k(this).dialog('close');
                    }
                }
            });
            $k("#removedialog").dialog('open'); 
            //return false;
     }
    /*]]>*/</script>
    <div id="removedialog" title="Remove a Company?">
        <p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
        This company will be permanently deleted and cannot be recovered. Are you sure?</p>
    </div>
Carlitux
  • 97
  • 1
  • 6
1

I have now tried your suggestions and found that it kinda works,

  1. The dialog div is alsways written out in plaintext
  2. With the $.post version it actually works in terms that the controller gets called and actually cancels the booking, but the dialog stays open and page doesn't refresh. With the get version window.location = h.ref works great.

Se my "new" script below:

$('a.cancel').click(function() {
        var a = this;               
        $("#dialog").dialog({
            autoOpen: false,
            buttons: {
                "Ja": function() {
                    $.post(a.href);                     
                },
                "Nej": function() { $(this).dialog("close"); }
            },
            modal: true,
            overlay: {
                opacity: 0.5,

            background: "black"
        }
    });
    $("#dialog").dialog('open');
    return false;
});

});

Any clues?

oh and my Action link now looks like this:

<%= Html.ActionLink("Cancel", "Cancel", new { id = v.BookingId }, new  { @class = "cancel" })%>
Frederik
  • 2,178
  • 4
  • 20
  • 20
1

Looking at your code what you need to do is add the functionality to close the window and update the page. In your "Yes" function you should write:

        buttons: {
            "Ja": function() {
                $.post(a.href);
                $(a). // code to remove the table row
                $("#dialog").dialog("close");
            },
            "Nej": function() { $(this).dialog("close"); }
        },

The code to remove the table row isn't fun to write so I'll let you deal with the nitty gritty details, but basically, you need to tell the dialog what to do after you post it. It may be a smart dialog but it needs some kind of direction.

thaBadDawg
  • 5,160
  • 6
  • 35
  • 44
  • Thanx for your answer. I will try it out and also find a way to remove the row... – Frederik Dec 28 '08 at 13:43
  • I was thinking about it, if you add an id to the '' tag then you might be able to get jQuery to remove that row easily enough. – thaBadDawg Dec 29 '08 at 20:57
1

This work for me:

<a href="#" onclick="sposta(100)">SPOSTA</a>

function sposta(id) {
        $("#sposta").data("id",id).dialog({
            autoOpen: true,
            modal: true,
            buttons: { "Sposta": function () { alert($(this).data('id')); } }
        });
    }

When you click on "Sposta" in dialog alert display 100

maurox
  • 1,254
  • 1
  • 19
  • 33
0

i hope this helps

$("#dialog-yesno").dialog({
    autoOpen: false,
    resizable: false,
    closeOnEscape: false,
    height:180,
    width:350,
    modal: true,
    show: "blind",
    open: function() {
        $(document).unbind('keydown.dialog-overlay');
        },
    buttons: {
        "Delete": function() {
            $(this).dialog("close");
            var dir = $(this).data('link').href;
            var arr=dir.split("-");
            delete(arr[1]);
        },
    "Cancel": function() {
        $(this).dialog("close");
        }
    }
});



<a href="product-002371" onclick="$( '#dialog-yesno' ).data('link', this).dialog( 'open' ); return false;">Delete</a>
Taryn
  • 242,637
  • 56
  • 362
  • 405
  • 1
    Hey @ffernandez, it's probably best to try and include some description of what you're doing - rather then just throwing code at the OP. – thomasfedb Jun 10 '12 at 07:54
0

Ok the first issue with the div tag was easy enough: I just added a style="display:none;" to it and then before showing the dialog I added this in my dialog script:

$("#dialog").css("display", "inherit");

But for the post version I'm still out of luck.

Frederik
  • 2,178
  • 4
  • 20
  • 20
0

A solution inspired by Boris Guery that I employed looks like this: The link:

<a href="#" class = "remove {id:15} " id = "mylink1" >This is my clickable link</a>

bind an action to it:

$('.remove').live({
        click:function(){
            var data = $('#'+this.id).metadata();
            var id = data.id;
            var name = data.name;
            $('#dialog-delete')
                .data('id', id)
                .dialog('open');    
            return false;
        }
    });

And then to access the id field (in this case with value of 15:

$('#dialog-delete').dialog({
    autoOpen: false,
    position:'top',
    width: 345,
    resizable: false,
    draggable: false,
    modal: true,
    buttons: {            
        Cancel: function() {

            $(this).dialog('close');
        },
        'Confirm delete': function() {
            var id = $(this).data('id');
            $.ajax({
                url:"http://example.com/system_admin/admin/delete/"+id,
                type:'POST',
                dataType: "json",
                data:{is_ajax:1},
                success:function(msg){

                }
            })
        }
    }
});
Kevin Bradshaw
  • 6,327
  • 13
  • 55
  • 78
0

Just give you some idea may help you, if you want fully control dialog, you can try to avoid use of default button options, and add buttons by yourself in your #dialog div. You also can put data into some dummy attribute of link, like Click. call attr("data") when you need it.