Передача данных в диалог пользовательского интерфейса jQuery

83

Я разрабатываю ASP.Net MVCсайт, и на нем я перечисляю некоторые бронирования из запроса к базе данных в таблице с возможностью ActionLinkотмены бронирования в определенной строке с определенным BookingIdследующим образом:

Мои бронирования

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

Было бы неплохо, если бы я мог использовать jQuery Dialogдля отображения всплывающего сообщения с вопросом, уверен ли пользователь, что хочет отменить бронирование. Я пытался заставить это работать, но я все время зацикливаюсь на том, как создать функцию jQuery, которая принимает параметры, чтобы я мог заменить

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

с участием

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

Затем ShowDialogфункция откроет диалоговое окно, а также передаст в диалоговое окно параметр 10, так что, если пользователь щелкнет Да, он отправит href:/Booking.aspx/Change/10

Я создал диалог jQuery в таком сценарии:

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

и сам диалог:

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

Итак, наконец, мой вопрос: как я могу этого добиться? или есть лучший способ сделать это?

Фредерик
источник

Ответы:

45

Сделать это можно так:

  • отметьте <a>классом, скажите "отменить"
  • настройте диалог, воздействуя на все элементы с помощью class = "cancel":

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

(плюс другие варианты)

Ключевые моменты здесь:

  • сделать это как можно ненавязчивее
  • Если вам нужен только URL-адрес, он у вас уже есть в href.

Однако я рекомендую вам сделать это POST вместо GET, поскольку действие отмены имеет побочные эффекты и, следовательно , не соответствует семантике GET ...

Маурисио Шеффер
источник
Спасибо за хороший ответ. Я попробую, но один вопрос. вы упомянули, что лучше сделать это POST вместо GET, что подразумевает, что обычный href, такой как href = "/ Booking.aspx / Cancel / 10", будет GET, верно? и если да, то что бы он хотел сделать постом?
Frederik
Чтобы сделать это постом, вместо изменения window.location вы можете использовать функцию jQuery $ .post () ajax. См. Docs.jquery.com/Ajax/jQuery.post#examples
Франк,
1
Я бы не стал использовать $ .post (), этот подход плохо ухудшается. Просто напишите стандартную <form> без какого-либо ajax, заставьте ее работать без подтверждения, а затем добавьте подтверждение «поверх» вашей <form>
Маурисио Шеффер
Это также известно как подход hijax ( domscripting.com/blog/display/41 )
Маурисио Шеффер,
Вам не обязательно использовать post, но если вы используете get для операции изменения базы данных, вы открываете себя для атаки «подделки межсайтового запроса» ... см .: en.wikipedia.org/wiki/Cross- site_request_forgery
strickli
273

jQuery предоставляет метод, который хранит данные для вас, нет необходимости использовать фиктивный атрибут или искать обходной путь для вашей проблемы.

Привяжите событие клика:

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

И ваш диалог:

$("#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
Это прекрасное решение. Я не знал, что вы можете установить данные в диалоговом окне, используя .data. Я много лет устанавливал глобальные переменные, обращаясь к ним из своих диалогов, а затем уничтожая их!
Кевин Брэдшоу,
Большое спасибо за эту магию .data (). Однако обратите внимание на следующее обновление: «Начиная с jQuery 1.7, метод .on () является предпочтительным методом для присоединения обработчиков событий к документу» api.jquery.com/bind
daniloquio
2
Параметр .data - это определенно путь. Благодаря!
Андреас
1
+1 Я искал документацию jquery ui и не мог найти ее, пока не понял, что это метод самого ядра jQuery. Очень хороший улов
Tivie 05
@ boris-guery Привет, я попробовал, но не удалось заставить его работать. Это просто не предотвращает действие по умолчанию, поэтому вместо открытия диалогового окна выполняется переход по ссылке. Любая помощь будет принята с благодарностью: я делаю jsfiddle: jsfiddle.net/sebababi/9zKcZ
Себастьян
2

Что касается того, что вы делаете с jQuery, я понимаю, что вы можете связывать функции, как у вас, а внутренние имеют доступ к переменным из внешних. Если ваша функция ShowDialog (x) содержит эти другие функции, вы можете повторно использовать в них переменную x, и она будет использоваться как ссылка на параметр из внешней функции.

Я согласен с mausch, вам действительно следует рассмотреть возможность использования POST для этих действий, который добавит <form>тег вокруг каждого элемента, но значительно снизит вероятность того, что автоматический скрипт или инструмент запустит событие Cancel. Действие «Изменить» можно оставить без изменений, потому что оно (предположительно, просто открывает форму редактирования).

Фалькайн
источник
1

Я попробовал ваши предложения и обнаружил, что это вроде работает,

  1. Диалоговое окно div всегда записывается в виде открытого текста.
  2. В версии $ .post он фактически работает в том смысле, что контроллер вызывается и фактически отменяет бронирование, но диалоговое окно остается открытым, а страница не обновляется. С версией get window.location = h.ref отлично работает.

Смотрите мой «новый» сценарий ниже:

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

});

Какие-нибудь подсказки?

о, и моя ссылка на действие теперь выглядит так:

<%= Html.ActionLink("Cancel", "Cancel", new { id = v.BookingId }, new  { @class = "cancel" })%>
Фредерик
источник
См. Мои комментарии к моему ответу об использовании $ .post () и подхода hijax
Маурисио Шеффер
1

Глядя на свой код, вам нужно добавить функцию закрытия окна и обновления страницы. В вашей функции «Да» вы должны написать:

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

Код для удаления строки таблицы писать неинтересно, поэтому я позволю вам разобраться с мелкими деталями, но в основном вам нужно указать диалоговому окну, что делать после его публикации. Это может быть умный диалог, но ему нужно какое-то направление.

thaBadDawg
источник
Спасибо за ваш ответ. Я попробую, а также найду способ удалить строку ...
Фредерик
Я думал об этом, если вы добавите идентификатор к тегу '<TR>', тогда вы сможете заставить jQuery достаточно легко удалить эту строку.
thaBadDawg
1

После НЕСКОЛЬКИХ ЧАСОВ try / catch я наконец пришел с этим рабочим примером, его работа с AJAX POST с новыми строками добавляется в ТАБЛИЦУ на лету (это была моя настоящая проблема):

Магия пришла со ссылкой на это:

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

Это последняя работа с AJAX POST и 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
источник
1

Эта работа для меня:

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

При нажатии на «Споста» в диалоговом окне отображается предупреждение 100

Maurox
источник
0

Хорошо, первая проблема с тегом div была достаточно простой: я просто добавил style="display:none;"к нему, а затем, прежде чем показывать диалог, я добавил это в свой сценарий диалога:

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

А вот с пост-версией мне все равно не повезло.

Фредерик
источник
См. Мои комментарии к моему ответу об использовании $ .post () и подхода hijax
Маурисио Шеффер
0

Просто дайте вам некоторую идею, которая может помочь вам, если вы хотите полностью контролировать диалог, вы можете попытаться избежать использования параметров кнопок по умолчанию и добавить кнопки самостоятельно в свой #dialog div. Вы также можете поместить данные в какой-нибудь фиктивный атрибут ссылки, например Click. вызовите attr ("данные"), когда вам это нужно.


источник
0

Решение, вдохновленное Борисом Гери, которое я использовал, выглядит так: Ссылка:

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

привязать к нему действие:

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

А затем для доступа к полю id (в данном случае со значением 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

надеюсь, это поможет

$("#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
источник
1
Привет, @ffernandez, вероятно, лучше попытаться включить некоторое описание того, что вы делаете, а не просто бросать код в OP.
thomasfedb