Pasar datos a un diálogo de interfaz de usuario de jQuery


83

Estoy desarrollando un ASP.Net MVCsitio y en él enumero algunas reservas de una consulta de base de datos en una tabla con un ActionLinkpara cancelar la reserva en una fila específica con un cierto BookingIdcomo este:

Mis reservas

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

Lo que sería bueno es si pudiera usar el jQuery Dialogpara abrir un mensaje preguntando si el usuario está seguro de que quiere cancelar la reserva. He estado intentando que esto funcione, pero sigo atascado en cómo crear una función jQuery que acepte parámetros para poder reemplazar el

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

con

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

La ShowDialogfunción luego abriría el cuadro de diálogo y también pasaría el parámetro 10 al cuadro de diálogo de modo que si el usuario hace clic en sí, se publicará el href:/Booking.aspx/Change/10

He creado el jQuery Dialog en un script como este:

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

y el diálogo en sí:

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

Así que finalmente a mi pregunta: ¿Cómo puedo lograr esto? ¿O hay una mejor forma de hacerlo?

Respuestas:


45

Podrías hacerlo así:

  • marcar el <a>con una clase, decir "cancelar"
  • configure el diálogo actuando sobre todos los elementos con class = "cancel":

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

(más tus otras opciones)

Los puntos clave aquí son:

  • hazlo lo más discreto posible
  • si todo lo que necesita es la URL, ya la tiene en el href.

Sin embargo, le recomiendo que haga de esto un POST en lugar de un GET, ya que una acción de cancelación tiene efectos secundarios y, por lo tanto , no cumple con la semántica GET ...


Gracias por una buena respuesta. Lo intentaré, aunque una pregunta. mencionas que es mejor convertirlo en un POST en lugar de un GET, lo que implica que un href regular como href = "/ Booking.aspx / Cancel / 10" sería un GET, ¿verdad? y si es así, ¿qué le gustaría convertirlo en una publicación?
Frederik

Para convertirlo en una publicación, en lugar de cambiar la ubicación de la ventana, puede usar la función jQuery $ .post () ajax. Ver docs.jquery.com/Ajax/jQuery.post#examples
Franck

1
No usaría $ .post (), ese enfoque no se degrada bien. Simplemente escriba un <form> estándar sin ningún ajax, hágalo funcionar sin confirmación y luego agregue la confirmación "en la parte superior" de su <form>
Mauricio Scheffer

Esto también se conoce como el enfoque hijax ( domscripting.com/blog/display/41 )
Mauricio Scheffer

No tiene que usar la publicación, pero si usa un get para una operación de alteración de la base de datos, se abre a un ataque de "falsificación de solicitud entre sitios" ... ver: en.wikipedia.org/wiki/Cross- site_request_forgery
strickli

273

jQuery proporciona un método que almacena datos por usted, sin necesidad de usar un atributo ficticio o encontrar una solución a su problema.

Vincular el evento de clic:

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

Y tu diálogo:

$("#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
Esta es una solución brillante. No sabía que se podían establecer datos en un cuadro de diálogo usando .data. He estado configurando variables globales durante años, accediendo a ellas desde mis cuadros de diálogo y luego destruyéndolas.
Kevin Bradshaw

Muchas gracias por esta magia .data (). Sin embargo, observe la siguiente actualización: "A partir de jQuery 1.7, el método .on () es el método preferido para adjuntar controladores de eventos a un documento" api.jquery.com/bind
daniloquio

2
El parámetro .data es definitivamente el camino a seguir. ¡Gracias!
Andreas

1
+1 He buscado en la documentación de la interfaz de usuario de jquery y no pude encontrar esto hasta que me di cuenta de que era un método del núcleo de jQuery. Muy buena captura
Tivie

@ boris-guery Hola, lo intenté, pero no pude hacerlo funcionar. Simplemente no evita la acción predeterminada, por lo que va al enlace en lugar de abrir el cuadro de diálogo. Cualquier ayuda sería apreciada: hago un jsfiddle: jsfiddle.net/sebababi/9zKcZ
Sebastian

2

En términos de lo que está haciendo con jQuery, tengo entendido que puede encadenar funciones como lo hizo y las internas tienen acceso a variables de las externas. Entonces, si su función ShowDialog (x) contiene estas otras funciones, puede reutilizar la variable x dentro de ellas y se tomará como una referencia al parámetro de la función externa.

Estoy de acuerdo con mausch, realmente debería considerar el uso de POST para estas acciones, que agregarán una <form>etiqueta alrededor de cada elemento, pero harán que las posibilidades de que un script o herramienta automatizada active el evento Cancel son mucho menos probables. La acción Cambiar puede permanecer como está porque (presumiblemente solo abre un formulario de edición).


1

Probé tus sugerencias y descubrí que funciona,

  1. El div de diálogo siempre está escrito en texto plano
  2. Con la versión $ .post, en realidad funciona en términos de que se llama al controlador y de hecho cancela la reserva, pero el cuadro de diálogo permanece abierto y la página no se actualiza. Con la versión get, window.location = h.ref funciona muy bien.

Vea mi "nuevo" script a continuación:

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

});

¿Alguna pista?

oh, y mi enlace de acción ahora se ve así:

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

Vea mis comentarios sobre mi respuesta sobre el uso de $ .post () y el enfoque hijax
Mauricio Scheffer

1

Al mirar su código, lo que debe hacer es agregar la funcionalidad para cerrar la ventana y actualizar la página. En su función "Sí" debe escribir:

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

El código para eliminar la fila de la tabla no es divertido de escribir, así que te dejaré lidiar con los detalles esenciales, pero básicamente, debes decirle al cuadro de diálogo qué hacer después de publicarlo. Puede ser un diálogo inteligente, pero necesita algún tipo de dirección.


Gracias por tu respuesta. Lo probaré y también encontraré una manera de eliminar la fila ...
Frederik

Estaba pensando en ello, si agrega una identificación a la etiqueta '<TR>', entonces es posible que jQuery elimine esa fila con la suficiente facilidad.
thaBadDawg

1

Después de VARIAS HORAS de intentar / atrapar, finalmente vine con este ejemplo de trabajo, está funcionando en AJAX POST con nuevas filas que se agregan a la TABLA sobre la marcha (ese era mi problema real):

La magia vino con este enlace:

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

Este es el trabajo final con AJAX POST y 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

Este trabajo para mi:

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

Al hacer clic en "Sposta" en la pantalla de alerta de diálogo 100


0

Ok, el primer problema con la etiqueta div fue bastante fácil: simplemente le agregué un style="display:none;"y luego, antes de mostrar el diálogo, agregué esto en mi script de diálogo:

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

Pero para la versión de publicación todavía no tengo suerte.


Vea mis comentarios sobre mi respuesta sobre el uso de $ .post () y el enfoque hijax
Mauricio Scheffer

0

Solo darle una idea puede ayudarlo, si desea controlar completamente el diálogo, puede intentar evitar el uso de las opciones de botón predeterminadas y agregar botones usted mismo en su div #dialog. También puede poner datos en algún atributo ficticio de enlace, como Click. llame a attr ("datos") cuando lo necesite.


0

Una solución inspirada en Boris Guery que empleé se ve así: El enlace:

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

vincularle una acción:

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

Y luego para acceder al campo id (en este caso con valor de 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

espero que esto ayude

$("#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
Hola @ffernandez, probablemente sea mejor intentar incluir una descripción de lo que estás haciendo, en lugar de simplemente arrojar código al OP.
thomasfedb
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.