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
Черт, проигнорируйте меня - извините, я только что понял, что ваш флаг dialogAppeared установлен только, когда пользователь нажимает "да". :-) - person xn dx; 29.02.2012
comment
Вы имеете в виду, если пользователь выбрал «Отмена»? Таким образом, dialogAppeared не будет иметь значение true (обратите внимание, что его устанавливает только кнопка «Да»). Может быть, мне следовало использовать лучшее имя для этого вара... [сделано] - person mgibsonbr; 29.02.2012
comment
Как странно, когда он, наконец, пытается отправить форму с возвратом 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 в var, а затем вызовет его без каких-либо this, я не думаю, что это вообще сработает. Даже если вы использовали $.proxy для привязки к нужному элементу, это все равно была бы та же самая функция, поэтому пользовательский обработчик вызывался бы снова. - person mgibsonbr; 29.02.2012
comment
Да, к сожалению, похоже, что вызов функции defaultSubmit() при нажатии кнопки «ОК» просто снова запускает функцию отправки, открывая диалоговое окно :( Я обновил свой первоначальный пост, чувствую, что прогресс есть, но бла - 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
Спасибо, я подумал об этом, но было бы неловко, когда пользователь отправляет форму, просто нажимая клавишу ввода. - person xn dx; 29.02.2012