Passer des données à une boîte de dialogue de l'interface utilisateur jQuery

83

Je développe un ASP.Net MVCsite et j'y répertorie certaines réservations à partir d'une requête de base de données dans une table avec un ActionLinkpour annuler la réservation sur une ligne spécifique avec un certain BookingIdcomme celui-ci:

Mes réservations

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

Ce serait bien si je pouvais utiliser le jQuery Dialogpour afficher un message demandant si l'utilisateur est sûr de vouloir annuler la réservation. J'ai essayé de faire fonctionner cela mais je n'arrête pas de me demander comment créer une fonction jQuery qui accepte les paramètres afin que je puisse remplacer le

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

avec

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

La ShowDialogfonction ouvrirait alors la boîte de dialogue et passerait également le paramètre 10 à la boîte de dialogue de sorte que si l'utilisateur clique sur oui, elle affichera le href:/Booking.aspx/Change/10

J'ai créé la boîte de dialogue jQuery dans un script comme celui-ci:

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

et le dialogue lui-même:

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

Alors finalement à ma question: comment puis-je accomplir cela? ou y a-t-il une meilleure façon de le faire?

Frederik
la source

Réponses:

45

Vous pouvez le faire comme ceci:

  • marquez le <a>avec une classe, dites "annuler"
  • configurer le dialogue en agissant sur tous les éléments avec class = "cancel":

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

(plus vos autres options)

Les points clés ici sont:

  • rendez-le aussi discret que possible
  • si vous n'avez besoin que de l'URL, vous l'avez déjà dans le href.

Cependant, je vous recommande d'en faire un POST au lieu d'un GET, car une action d'annulation a des effets secondaires et n'est donc pas conforme à la sémantique GET ...

Mauricio Scheffer
la source
Merci pour une bonne réponse. Je vais l'essayer, une question cependant. vous mentionnez qu'il vaut mieux en faire un POST au lieu d'un GET, ce qui implique qu'un href normal comme href = "/ Booking.aspx / Cancel / 10" serait un GET est-ce exact? et si oui, qu'est-ce que ça ferait pour en faire un message alors?
Frederik
Afin d'en faire un article, au lieu de changer la window.location, vous pouvez utiliser la fonction ajax jQuery $ .post (). Voir docs.jquery.com/Ajax/jQuery.post#examples
Franck
1
Je n'utiliserais pas $ .post (), cette approche ne se dégrade pas bien. Écrivez simplement un <form> standard sans ajax, faites-le fonctionner sans confirmation, puis ajoutez la confirmation "en haut" de votre <form>
Mauricio Scheffer
Ceci est également connu sous le nom d'approche hijax ( domscripting.com/blog/display/41 )
Mauricio Scheffer
Vous n'êtes pas obligé d'utiliser post, mais si vous utilisez un get pour une opération de modification de base de données, vous vous ouvrez à une attaque de type "falsification de requête intersite" ... voir: en.wikipedia.org/wiki/Cross- site_request_forgery
strickli
273

jQuery fournit une méthode qui stocke les données pour vous, pas besoin d'utiliser un attribut factice ou de trouver une solution de contournement à votre problème.

Liez l'événement 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');
});

Et votre dialogue:

$("#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
la source
15
C'est une solution brillante. Je ne savais pas que vous pouviez définir des données sur une boîte de dialogue en utilisant .data J'ai défini des variables globales depuis des lustres, en y accédant à partir de mes boîtes de dialogue et en les détruisant!
Kevin Bradshaw
Merci beaucoup pour cette magie .data (). Notez cependant la mise à jour suivante: "Depuis jQuery 1.7, la méthode .on () est la méthode préférée pour attacher des gestionnaires d'événements à un document" api.jquery.com/bind
daniloquio
2
Le paramètre .data est définitivement la voie à suivre. Merci!
Andreas
1
+1 J'ai cherché dans la documentation de jquery ui et je n'ai pas pu trouver cela jusqu'à ce que je réalise que c'était une méthode du noyau jQuery lui-même. Très belle prise
Tivie
@ boris-guery Salut, je l'ai essayé, mais je n'ai pas réussi à le faire fonctionner. Cela n'empêche tout simplement pas l'action par défaut, il va donc vers le lien au lieu d'ouvrir la boîte de dialogue. Toute aide serait appréciée: je crée un jsfiddle: jsfiddle.net/sebababi/9zKcZ
Sebastian
2

En ce qui concerne ce que vous faites avec jQuery, je crois comprendre que vous pouvez chaîner des fonctions comme vous l'avez fait et que les fonctions internes ont accès aux variables des externes. Si votre fonction ShowDialog (x) contient ces autres fonctions, vous pouvez réutiliser la variable x qu'elles contiennent et elle sera considérée comme une référence au paramètre de la fonction externe.

Je suis d'accord avec mausch, vous devriez vraiment envisager d'utiliser POST pour ces actions, qui ajoutera une <form>balise autour de chaque élément, mais rendra beaucoup moins probables qu'un script ou un outil automatisé déclenche l'événement Cancel. L'action Modifier peut rester telle quelle car elle (ouvre vraisemblablement simplement un formulaire d'édition).

Falkayn
la source
1

J'ai maintenant essayé vos suggestions et j'ai trouvé que cela fonctionne un peu,

  1. Le div de dialogue est toujours écrit en texte brut
  2. Avec la version $ .post, cela fonctionne en fait en ce que le contrôleur est appelé et annule réellement la réservation, mais la boîte de dialogue reste ouverte et la page ne s'actualise pas. Avec la version get window.location = h.ref fonctionne très bien.

Voir mon "nouveau" script ci-dessous:

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

});

Des indices?

oh et mon lien d'action ressemble maintenant à ceci:

<%= Html.ActionLink("Cancel", "Cancel", new { id = v.BookingId }, new  { @class = "cancel" })%>
Frederik
la source
Voir mes commentaires sur ma réponse sur l'utilisation de $ .post () et l'approche hijax
Mauricio Scheffer
1

En regardant votre code, ce que vous devez faire est d'ajouter la fonctionnalité pour fermer la fenêtre et mettre à jour la page. Dans votre fonction "Oui", vous devez écrire:

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

Le code pour supprimer la ligne du tableau n'est pas amusant à écrire, je vous laisse donc gérer les détails, mais en gros, vous devez dire à la boîte de dialogue ce qu'il faut faire après l'avoir posté. C'est peut-être un dialogue intelligent, mais il a besoin d'une sorte de direction.

thaBadDawg
la source
Merci pour votre réponse. Je vais l'essayer et trouver un moyen de supprimer la ligne ...
Frederik
J'y pensais, si vous ajoutez un identifiant à la balise '<TR>', vous pourrez peut-être demander à jQuery de supprimer cette ligne assez facilement.
thaBadDawg
1

Après PLUSIEURS HEURES de try / catch, je suis finalement arrivé avec cet exemple de travail, il fonctionne sur AJAX POST avec de nouvelles lignes ajoutées à la table à la volée (c'était mon vrai problème):

La magie est venue avec le lien ceci:

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

C'est le dernier travail avec AJAX POST et 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
la source
1

Ce travail pour moi:

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

Lorsque vous cliquez sur «Sposta» dans la boîte de dialogue, l’alerte affiche 100

Maurox
la source
0

Ok, le premier problème avec la balise div était assez simple: je viens d'y ajouter un style="display:none;", puis avant d'afficher la boîte de dialogue, j'ai ajouté ceci dans mon script de dialogue:

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

Mais pour la version post, je n'ai toujours pas de chance.

Frederik
la source
Voir mes commentaires sur ma réponse sur l'utilisation de $ .post () et l'approche hijax
Mauricio Scheffer
0

Donnez-vous juste une idée qui peut vous aider, si vous voulez contrôler entièrement la boîte de dialogue, vous pouvez essayer d'éviter d'utiliser les options de bouton par défaut et ajouter des boutons par vous-même dans votre div #dialog. Vous pouvez également mettre des données dans un attribut factice de lien, comme Click. appelez attr ("data") quand vous en avez besoin.


la source
0

Une solution inspirée de Boris Guery que j'ai employée ressemble à ceci: Le lien:

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

lier une action à celui-ci:

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

Et puis pour accéder au champ id (dans ce cas avec une valeur 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){

                }
            })
        }
    }
});
Kevin Bradshaw
la source
0

J'espère que ça aide

$("#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>
Fernandez
la source
1
Hé @ffernandez, il est probablement préférable d'essayer d'inclure une description de ce que vous faites - plutôt que de simplement lancer du code sur l'OP.
thomasfedb