jQuery при валидиране на изпращане, с модален диалогов прозорец в края?

В момента имам формуляр, който бих искал да потвърдя, и ако приемем, че всичко е правилно, бих искал след това да изскача диалогов прозорец, потвърждаващ техните подробности, ето пример за кода, който имам досега:

var userConfirmed = false;

$("#dialog").dialog({
    buttons: {
        "Yes": function() {
            userConfirmed = true;
            $("#inputform").submit();
        },
        "No, I'll change them.": function() {
            $(this).dialog("close");
        }
    }
});

// check they've submitted what they need to
$("form").submit(function() {

    // lots of these
    if (something) {
        return false;
    }

    $("#dialog").dialog("open");

    return userConfirmed;

});

Първоначалното валидиране работи добре - проверява спрямо критериите и маркира като подходящо и ако нито един от тези критерии не е изпълнен, ще покаже модалното поле точно както искам. Дотук добре.

Проблемът обаче е, че когато натисна „да“, за да изпратя формуляра, той не се изпраща, докато не натиснете отново същинския бутон „изпращане“, ах! Всяко обаждане за изпращане на форума с помощта на jQuery е неуспешно.

Всякакви предложения ще бъдат добре дошли, благодаря.


person xn dx    schedule 29.02.2012    source източник
comment
Опитах се да премахна целия код с изключение на този - pastebin.com/iUARx8CM - все още няма радост...   -  person xn dx    schedule 29.02.2012


Отговори (4)


Добавете някъде флаг, показващ дали диалоговият прозорец вече се е появил или не и потребителят е щракнал да. Пример:

var userConfirmed = false;
$("form").submit(function(e) {
    if ( userConfirmed ) {
        userConfirmed = false; // Reset it to false
        return true; // No need to validate anything, that was already done last time
    }
    var form = $(this);
    // ...
        "Yes": function() {
            userConfirmed = true; // Confirm that the dialog was shown and the user clicked "Yes"
            $(this).dialog("close");
            form.submit(); // Try again; this time, the validation was already done
        },
    // ...
    return false; // Don't submit; the user haven't confirmed the info on the dialog
});

Без този флаг ще бъдете в ситуация на кокошка и яйце: изпращането отваря диалоговия прозорец и диалоговият прозорец, извикващ $("form").submit(), отваря диалоговия прозорец отново...

Ако имате много форми и не искате да използвате "глобална" променлива, можете да използвате data за същата цел.

Актуализация: пример на живо в jsFiddle. Тествано с успех в Chrome и Firefox (ще покаже празна страница 3 секунди след изпращане).

person mgibsonbr    schedule 29.02.2012
comment
Това е добра идея, благодаря. Основното ми притеснение е, че ако диалоговият прозорец бъде представен на потребителя и той редактира своите данни, той няма да се появи отново с последна подкана, преди да изпрати. Знам, че звучи като гаден дизайн, но е изискване за съжаление :$ - person xn dx; 29.02.2012
comment
По дяволите, игнорирайте ме - съжалявам, едва сега разбрах, че флагът ви за диалогов прозорец се показва само, когато потребителят щракне с „да“. :-) - person xn dx; 29.02.2012
comment
Имате предвид, ако потребителят избере Отказ? По този начин dialogAppeared няма да бъде зададено на true (имайте предвид, че само бутонът Yes го задава). Може би трябваше да използвам по-добро име за тази променлива... [готово] - person mgibsonbr; 29.02.2012
comment
Колко странно, когато най-накрая се опитва да изпрати формуляра с return true; нищо не се случва. Спира процеса на валидиране, както трябва, но не изпраща формуляра, докато не натисна ръчно бутона отново? :/ - person xn dx; 29.02.2012
comment
Променено окончателното връщане false; за връщане на userConfirmed; - изглеждаше добра идея по онова време, но все още не работи - person xn dx; 29.02.2012
comment
Това е странно... За съжаление не мога да ви помогна с това. Но актуализираният отговор от remibreton+PCasagrande изглежда обещаващ, бих казал дори по-чист от моя, можете да опитате това вместо това - person mgibsonbr; 29.02.2012
comment
Добавен пример на живо в jsFiddle и той работи добре. Обзалагам се, че някакво изключение е хвърлено във вашия бутон Да, което не сте забелязали, затова е работило само след повторно щракване върху бутона (променливата все още беше вярна в този момент) - person mgibsonbr; 29.02.2012

както винаги препоръчвам използването на jQuery validate за валидиране, тогава кодът ще изглежда така

$("#formid").validate({
    submitHandler: function(form) {
               $("#dialog").dialog({
     buttons: {
         "Ok": function() {
             form.submit();
             $(this).dialog("close");
         },
         "Cancel": function() {
             $(this).dialog("close");
         }
     }
});
    }
});

ДЕМО НА ЖИВО

person mcgrailm    schedule 29.02.2012
comment
Много благодаря, исках да избегна външен плъгин, ако е възможно, но изглежда, че вероятно трябва да проверя този - person xn dx; 29.02.2012
comment
Струва си да се отбележи, че този плъгин е създаден от член на екипа на jQuery и се използва широко за валидиране на формуляри и ще ви спести много време за писане на код - person mcgrailm; 29.02.2012
comment
Току-що се опитах да внедря това, много е добро (благодаря), но е масово несъвместимо с начина, по който се генерират грешки в сайта в момента (използване на jGrowl извиквания и фокусиране върху елемента с грешката) и в резултат на това ще отнеме абсурдно голям време за прилагане :( Все пак благодаря, това е добро предложение. - person xn dx; 29.02.2012

Фактът, че диалоговият прозорец се отваря, не спира изпълнението на кода. valToReturn се връща от $("form").submit() още преди да е зададено.

Бихте могли да направите нещо подобно:

//Save the default behavior to break any loops
var defaultSubmit = $.extend(true, {}, $("form").submit);

$("form").submit(function(e) {

    var valToReturn = true;

    // lots of these
    if (something) {
        return false;
    }

    // popup the dialog confirmation
    $("#dialog").dialog({
        buttons: {
            "Ok": function() {
                $(this).dialog("close");
                defaultSubmit(); // User confirmed, submit form.
            },
            "Cancel": function() {
                $(this).dialog("close"); // Form already prevented from submitting. Exit quietly.
            }
        }
    });

    $("#dialog").dialog("open");

    return false; // Prevent form from being submitted

});
person Rémi Breton    schedule 29.02.2012
comment
Ах! Благодаря ви за актуализацията :) Това е хубава идея, опитах я точно преди да публикувам, но за съжаление причинява безкраен цикъл на постоянни опити за извикване на функцията form.submit - person xn dx; 29.02.2012
comment
Опитайте да запазите съществуващия $("form").submit() в променлива и след това променете функционалността с jQuery. Във вашата функция OK можете просто да извикате запазената версия и формулярът ще се обработи правилно. - person PCasagrande; 29.02.2012
comment
Благодаря за актуализацията, за съжаление все още води до безкраен цикъл - person xn dx; 29.02.2012
comment
Харесва ми общата идея за запазване на последния манипулатор, но този код наистина ли ще го направи? От това, което успях да прочета, ще запази $.fn.submit във променлива, след което ще го извика без this, не мисля, че това изобщо ще работи. Дори ако сте използвали $.proxy, за да го свържете към правилния елемент, това пак ще бъде същата функция, така че потребителският манипулатор ще бъде извикан отново. - person mgibsonbr; 29.02.2012
comment
Да, за съжаление изглежда, че извикването на функцията defaultSubmit() при натискане на бутона „Ok“ просто стартира отново функцията за изпращане, изскачайки диалоговия прозорец :( Актуализирах първоначалната си публикация, чувствам, че има напредък, но др - person xn dx; 29.02.2012
comment
Подадох промяна; Забравих, че javascript актуализира променливи по този начин. Решението е да използвате var defaultSubmit = $.extend(true, {}, $("form").submit); Това, което прави, е да запази копие, а не препратка към цялото нещо, в празен обект. - person PCasagrande; 29.02.2012

Бих прикачил събитието към бутон вместо към формуляра. Просто го прикачете към щракване на бутон за изпращане. След това можете да използвате event.preventDefault(), за да предотвратите изпращането на формуляра, докато диалогът не бъде потвърден. Във функцията „Да“ просто поставете $('form').submit(). Няма нужда да се притеснявате и за върнатата стойност по този начин.

person PCasagrande    schedule 29.02.2012
comment
Благодаря ви, обмислих това, но би било неудобно, когато потребител изпрати формуляр просто като натисне клавиша enter. - person xn dx; 29.02.2012