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?

Frederik
źródło

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

Mauricio Scheffer
źródło
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);
        }
    }
});
Boris Guéry
źródło
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).

Falkayn
źródło
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" })%>
Frederik
źródło
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.

thaBadDawg
źródło
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>
Carlitux
źródło
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

Maurox
źródło
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.

Frederik
źródło
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.


źródło
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){

                }
            })
        }
    }
});
Kevin Bradshaw
źródło
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>
ffernandez
źródło
1
Hej @ffernandez, prawdopodobnie najlepiej jest spróbować dołączyć opis tego, co robisz - zamiast po prostu wrzucić kod do OP.
thomasfedb