Übergeben von Daten an einen jQuery UI-Dialog


83

Ich entwickle eine ASP.Net MVCSite und liste darauf einige Buchungen aus einer Datenbankabfrage in einer Tabelle mit einem ActionLinkauf, um die Buchung in einer bestimmten Zeile mit einem bestimmten BookingIdwie folgt zu stornieren :

Meine Buchungen

<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>

Was wäre schön, wenn ich das verwenden könnte, um jQuery Dialogeine Nachricht zu öffnen, in der gefragt wird, ob der Benutzer sicher ist, dass er die Buchung stornieren möchte. Ich habe versucht, dies zum Laufen zu bringen, aber ich bin immer wieder dabei, eine jQuery-Funktion zu erstellen, die Parameter akzeptiert, damit ich die ersetzen kann

<a href="https://stackoverflow.com/Booking.aspx/Cancel/10">cancel</a>

mit

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

Die ShowDialogFunktion würde dann den Dialog öffnen und auch den Parameter 10 an den Dialog übergeben, so dass, wenn der Benutzer auf Ja klickt, die href:/Booking.aspx/Change/10

Ich habe den jQuery-Dialog in einem Skript wie dem folgenden erstellt:

$(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"
        }
    });
});   

und der Dialog selbst:

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

Also endlich zu meiner Frage: Wie kann ich das erreichen? oder gibt es einen besseren weg dazu?

Antworten:


45

Sie könnten es so machen:

  • Markieren Sie das <a>mit einer Klasse und sagen Sie "Abbrechen".
  • Richten Sie den Dialog ein, indem Sie auf alle Elemente mit class = "cancel" einwirken:

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

(plus Ihre anderen Optionen)

Die wichtigsten Punkte hier sind:

  • mach es so unauffällig wie möglich
  • Wenn Sie nur die URL benötigen, haben Sie diese bereits in der href.

Ich empfehle jedoch, dass Sie dies als POST anstelle eines GET festlegen, da eine Abbruchaktion Nebenwirkungen hat und daher nicht der GET-Semantik entspricht ...


Vielen Dank für eine gute Antwort. Ich werde es ausprobieren, aber eine Frage. Sie erwähnen, dass es besser ist, einen POST anstelle eines GET zu erstellen, was impliziert, dass ein regulärer href wie href = "/ Booking.aspx / Cancel / 10" ein GET wäre, stimmt das? und wenn ja, wie würde es sich freuen, daraus einen Beitrag zu machen?
Frederik

Um daraus einen Beitrag zu machen, können Sie anstelle der Option window.location die Ajax-Funktion jQuery $ .post () verwenden. Siehe docs.jquery.com/Ajax/jQuery.post#examples
Franck

1
Ich würde $ .post () nicht verwenden, dieser Ansatz verschlechtert sich nicht gut. Schreiben Sie einfach ein Standard <Formular> ohne Ajax, lassen Sie es ohne Bestätigung funktionieren und fügen Sie dann die Bestätigung "oben" auf Ihrem <Formular> hinzu
Mauricio Scheffer

Dies ist auch als Hijax-Ansatz bekannt ( domscripting.com/blog/display/41 )
Mauricio Scheffer

Sie müssen nicht haben , um Post zu verwenden, aber wenn Sie ein get für einen Datenbank-Änderungsvorgang zu verwenden, öffnen Sie sich zu einem „Cross-Site - Request - Forgery“ Angriff ... siehe: en.wikipedia.org/wiki/Cross- site_request_forgery
strickli

273

jQuery bietet eine Methode, mit der Daten für Sie gespeichert werden, ohne dass ein Dummy-Attribut verwendet oder eine Problemumgehung für Ihr Problem gefunden werden muss.

Binden Sie das Klickereignis:

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

Und dein 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);
        }
    }
});

15
Dies ist eine brillante Lösung. Mir war nicht bewusst, dass Sie Daten in einem Dialog mit .data festlegen können. Ich habe seit Ewigkeiten globale Variablen festgelegt, über meine Dialoge darauf zugegriffen und sie dann zerstört!
Kevin Bradshaw

Vielen Dank für diese .data () Magie. Beachten Sie jedoch das folgende Update: "Ab jQuery 1.7 ist die .on () -Methode die bevorzugte Methode zum Anhängen von Ereignishandlern an ein Dokument." Api.jquery.com/bind
daniloquio

2
Der Parameter .data ist definitiv der richtige Weg. Vielen Dank!
Andreas

1
+1 Ich habe die jquery ui-Dokumentation durchsucht und konnte diese nicht finden, bis mir klar wurde, dass dies eine Methode aus dem jQuery-Kern selbst ist. Sehr schöner Fang
Tivie

@ boris-guery Hallo, ich habe es versucht, aber es nicht geschafft, dass es funktioniert. Die Standardaktion wird dadurch einfach nicht verhindert, sodass der Link aufgerufen wird, anstatt den Dialog zu öffnen. Jede Hilfe wäre dankbar: Ich mache eine jsfiddle: jsfiddle.net/sebababi/9zKcZ
Sebastian

2

In Bezug auf das, was Sie mit jQuery tun, ist mein Verständnis, dass Sie Funktionen wie Sie verketten können und die inneren Zugriff auf Variablen von den äußeren haben. Wenn Ihre ShowDialog (x) -Funktion diese anderen Funktionen enthält, können Sie die darin enthaltene x-Variable wiederverwenden und sie wird als Referenz auf den Parameter der äußeren Funktion verwendet.

Ich stimme mausch zu. Sie sollten sich wirklich die Verwendung von POST für diese Aktionen ansehen, bei denen ein <form>Tag um jedes Element hinzugefügt wird , aber die Wahrscheinlichkeit, dass ein automatisiertes Skript oder Tool das Ereignis "Abbrechen" auslöst, sehr viel geringer ist. Die Aktion Ändern kann unverändert bleiben, da sie vermutlich nur ein Bearbeitungsformular öffnet.


1

Ich habe jetzt Ihre Vorschläge ausprobiert und festgestellt, dass es irgendwie funktioniert,

  1. Der Dialog div ist immer im Klartext geschrieben
  2. Mit der $ .post-Version funktioniert es tatsächlich so, dass der Controller aufgerufen wird und die Buchung tatsächlich storniert, der Dialog jedoch geöffnet bleibt und die Seite nicht aktualisiert wird. Mit der get version window.location = h.ref funktioniert das super.

Siehe mein "neues" Skript unten:

$('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;
});

});

Irgendwelche Hinweise?

Oh, und mein Action-Link sieht jetzt so aus:

<%= Html.ActionLink("Cancel", "Cancel", new { id = v.BookingId }, new  { @class = "cancel" })%>

Siehe meine Kommentare zu meiner Antwort über die Verwendung von $ .post () und den Hijax-Ansatz
Mauricio Scheffer

1

Wenn Sie sich Ihren Code ansehen, müssen Sie die Funktionalität hinzufügen, um das Fenster zu schließen und die Seite zu aktualisieren. In Ihrer "Ja" -Funktion sollten Sie schreiben:

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

Das Schreiben des Codes zum Entfernen der Tabellenzeile macht keinen Spaß, daher lasse ich Sie sich mit den Details befassen, aber im Grunde müssen Sie dem Dialogfeld mitteilen, was zu tun ist, nachdem Sie ihn veröffentlicht haben. Es mag ein kluger Dialog sein, aber es braucht eine Richtung.


Vielen Dank für Ihre Antwort. Ich werde es ausprobieren und auch einen Weg finden, die Reihe zu entfernen ...
Frederik

Ich habe darüber nachgedacht. Wenn Sie dem Tag '<TR>' eine ID hinzufügen, können Sie jQuery möglicherweise dazu bringen, diese Zeile leicht genug zu entfernen.
thaBadDawg

1

Nach MEHREREN STUNDEN von try / catch kam ich endlich zu diesem Arbeitsbeispiel. Die Arbeit an AJAX POST mit neuen Zeilen wird im laufenden Betrieb an die TABELLE angehängt (das war mein eigentliches Problem):

Die Magie kam mit folgendem Link:

<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>

Dies ist die letzte Arbeit mit AJAX POST und 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>

1

Diese Arbeit für mich:

<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')); } }
        });
    }

Wenn Sie in der Dialogalarmanzeige 100 auf "Sposta" klicken


0

Ok, das erste Problem mit dem div-Tag war einfach genug: Ich habe gerade ein hinzugefügt style="display:none;"und bevor ich den Dialog anzeigte, habe ich dies in meinem Dialogskript hinzugefügt:

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

Aber für die Post-Version habe ich immer noch kein Glück.


Siehe meine Kommentare zu meiner Antwort über die Verwendung von $ .post () und den Hijax-Ansatz
Mauricio Scheffer

0

Geben Sie nur eine Idee, die Ihnen helfen kann. Wenn Sie den Dialog vollständig steuern möchten, können Sie versuchen, die Verwendung von Standardschaltflächenoptionen zu vermeiden, und selbst Schaltflächen in Ihrem #dialog div hinzufügen. Sie können Daten auch in ein Dummy-Attribut eines Links wie Click einfügen. Rufen Sie attr ("data") auf, wenn Sie es brauchen.


0

Eine von Boris Guery inspirierte Lösung, die ich verwendet habe, sieht folgendermaßen aus: Der Link:

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

binde eine Aktion daran:

$('.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;
        }
    });

Und dann, um auf das ID-Feld zuzugreifen (in diesem Fall mit dem Wert 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){

                }
            })
        }
    }
});

0

ich hoffe das hilft

$("#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>

1
Hey @ffernandez, es ist wahrscheinlich am besten, eine Beschreibung dessen zu geben, was Sie tun - anstatt nur Code auf das OP zu werfen.
Thomasfedb
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.