Przekazywanie danych do okna dialogowego interfejsu użytkownika jQuery


83

Rozwijam ASP.Net MVCwitrynę i na niej wypisuję rezerwacje z zapytania bazy danych w tabeli z ActionLinkklauzulą ​​anulowania rezerwacji w określonym wierszu z pewnym BookingIdtakim:

Moje rezerwacje

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

Byłoby miło, gdybym mógł użyć jQuery Dialogwyskakującego komunikatu z pytaniem, czy użytkownik jest pewien, że chce anulować rezerwację. Próbowałem, aby to zadziałało, ale wciąż utknąłem na tym, jak utworzyć funkcję jQuery, która akceptuje parametry, aby móc zastąpić

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

z

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

ShowDialogFunkcja będzie wtedy otworzyć okno, a także zdać paramter 10 do okna tak, że jeśli użytkownik kliknie tak to będzie opublikować href:/Booking.aspx/Change/10

Stworzyłem okno dialogowe jQuery w następującym skrypcie:

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

i samo okno dialogowe:

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

Na koniec na moje pytanie: jak mogę to osiągnąć? czy jest na to lepszy sposób?

Odpowiedzi:


45

Możesz to zrobić tak:

  • oznacz <a>klasą, powiedz „anuluj”
  • skonfiguruj okno dialogowe, działając na wszystkich elementach z class = "cancel":

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

(plus inne opcje)

Kluczowe punkty to:

  • uczyń go tak dyskretnym, jak to tylko możliwe
  • jeśli potrzebujesz tylko adresu URL, masz go już w href.

Zalecam jednak, aby uczynić to POST zamiast GET, ponieważ akcja anulowania ma skutki uboczne i dlatego nie jest zgodna z semantyką GET ...


Dzięki za dobrą odpowiedź. Spróbuję tego, chociaż jedno pytanie. wspomniałeś, że lepiej zrobić to POST zamiast GET, co oznacza, że ​​zwykły href, taki jak href = "/ Booking.aspx / Cancel / 10", byłby GET to prawda? a jeśli tak, to co by było, gdyby to był post?
Frederik,

Aby uczynić to postem, zamiast zmieniać window.location, możesz użyć funkcji jQuery $ .post () ajax. Zobacz docs.jquery.com/Ajax/jQuery.post#examples
Franck,

1
Nie użyłbym $ .post (), to podejście nie degraduje się dobrze. Po prostu napisz standardowy <form> bez żadnego Ajax, spraw, aby działał bez potwierdzenia, a następnie dodaj potwierdzenie „na wierzchu” swojego <formularza>
Mauricio Scheffer

Jest to również znane jako podejście hijax ( domscripting.com/blog/display/41 )
Mauricio Scheffer

Nie musisz używać postu, ale jeśli używasz get do operacji zmiany bazy danych, otwierasz się na atak typu „cross-site request fraegery” ... zobacz: en.wikipedia.org/wiki/Cross- site_request_forgery
strickli

273

jQuery zapewnia metodę, która przechowuje dane za Ciebie, bez potrzeby używania atrybutu fikcyjnego lub znajdowania obejścia problemu.

Powiązanie zdarzenia kliknięcia:

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

I twój 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
To genialne rozwiązanie. Nie wiedziałem, że możesz ustawić dane w oknie dialogowym za pomocą .data. Od wieków ustawiałem zmienne globalne, uzyskując do nich dostęp z moich okien dialogowych, a następnie je niszcząc!
Kevin Bradshaw

Bardzo dziękuję za tę magię .data (). Zwróć jednak uwagę na następującą aktualizację: „Od jQuery 1.7 metoda .on () jest preferowaną metodą dołączania programów
daniloquio

2
Parametr .data jest zdecydowanie drogą do zrobienia. Dzięki!
Andreas

1
+1 Przeszukałem dokumentację jQuery ui i nie mogłem tego znaleźć, dopóki nie zdałem sobie sprawy, że jest to metoda z samego rdzenia jQuery. Bardzo fajny chwyt
Tivie

@ boris-guery Cześć, próbowałem, ale nie udało mi się. Po prostu nie zapobiega domyślnej akcji, więc przechodzi do łącza zamiast otwierania okna dialogowego. Każda pomoc byłaby mile widziana: robię
Sebastian

2

Jeśli chodzi o to, co robisz z jQuery, rozumiem, że możesz łączyć funkcje, takie jak masz, a wewnętrzne mają dostęp do zmiennych z zewnętrznych. Więc jeśli twoja funkcja ShowDialog (x) zawiera te inne funkcje, możesz ponownie użyć w nich zmiennej x i zostanie ona wzięta jako odniesienie do parametru z funkcji zewnętrznej.

Zgadzam się z Mauschem, naprawdę powinieneś przyjrzeć się używaniu POST do tych działań, co doda <form>tag wokół każdego elementu, ale znacznie zmniejszy prawdopodobieństwo, że zautomatyzowany skrypt lub narzędzie wyzwoli zdarzenie Anuluj. Akcja Zmień może pozostać niezmieniona, ponieważ jest (prawdopodobnie po prostu otwiera formularz edycji).


1

Wypróbowałem teraz Twoje sugestie i stwierdziłem, że to trochę działa,

  1. Div dialog jest zawsze zapisywany w postaci zwykłego tekstu
  2. W wersji $ .post działa to w ten sposób, że kontroler jest wywoływany i faktycznie anuluje rezerwację, ale okno dialogowe pozostaje otwarte, a strona nie jest odświeżana. Z wersją do pobrania window.location = h.ref działa świetnie.

Zobacz mój „nowy” skrypt poniżej:

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

});

Jakieś wskazówki?

oh i mój link do akcji wygląda teraz następująco:

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

Zobacz moje komentarze na temat mojej odpowiedzi dotyczącej używania $ .post () i podejścia hijax
Mauricio Scheffer,

1

Patrząc na swój kod, musisz dodać funkcjonalność, aby zamknąć okno i zaktualizować stronę. W funkcji „Tak” należy wpisać:

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

Kod do usuwania wiersza tabeli nie jest przyjemny do napisania, więc pozwolę ci zająć się drobiazgowymi szczegółami, ale w zasadzie musisz powiedzieć dialogowi, co zrobić po opublikowaniu. Może to być sprytny dialog, ale wymaga jakiegoś kierunku.


Dzięki za odpowiedź. Spróbuję i znajdę sposób na usunięcie rzędu ...
Frederik

Zastanawiałem się nad tym, jeśli dodasz identyfikator do tagu „<TR>”, być może uda Ci się uzyskać w jQuery łatwe usunięcie tego wiersza.
thaBadDawg

1

Po KILKU GODZINACH try / catch w końcu przyszedłem z tym działającym przykładem, jego praca na AJAX POST z nowymi wierszami dołączanymi do TABLE w locie (to był mój prawdziwy problem):

Magia przyszła z linkiem:

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

Oto ostatnia praca z AJAX POST i 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

Ta praca dla mnie:

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

Po kliknięciu „Sposta” w oknie dialogowym pojawi się komunikat o błędzie 100


0

Ok, pierwszy problem ze znacznikiem DIV był dość łatwy: właśnie dodałem style="display:none;"do niego a, a następnie przed wyświetleniem okna dialogowego dodałem to w moim skrypcie dialogowym:

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

Ale w przypadku wersji post wciąż nie mam szczęścia.


Zobacz moje komentarze na temat mojej odpowiedzi dotyczącej używania $ .post () i podejścia hijax
Mauricio Scheffer,

0

Podaj tylko pewien pomysł, który może ci pomóc, jeśli chcesz w pełni kontrolować okno dialogowe, możesz spróbować uniknąć używania domyślnych opcji przycisków i samodzielnie dodawać przyciski w swoim #dialog div. Możesz również umieścić dane w jakimś fikcyjnym atrybucie linku, takim jak Click. call attr ("data"), kiedy tego potrzebujesz.


0

Rozwiązanie zainspirowane przez Borisa Guery'ego, które zastosowałem, wygląda następująco: Link:

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

powiąż z nim akcję:

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

A potem dostęp do pola id (w tym przypadku z wartością 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

mam nadzieję, że to pomoże

$("#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
Hej @ffernandez, prawdopodobnie najlepiej jest spróbować dołączyć opis tego, co robisz - zamiast po prostu wrzucić kod do OP.
thomasfedb
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.