Как получить ненавязчивый удаленный валидатор jquery для выполнения асинхронных ..? - PullRequest
7 голосов
/ 20 октября 2011

В приложении MVC3 с использованием ненавязчивой проверки jquery и представления / модели с [удаленным] валидатором: я пытаюсь отключить кнопку отправки и отобразить значок ожидания во время удаленной проверки, а также при отправке действительной формы всервер.Я думал, что это было прибито, пока я не попробовал это в IE8.

Проблема была в том, что GC и FF не запускали событие отправки формы, когда форма была недействительной, поэтому я просто отключил кнопку отправки во время этого события.Однако IE8 запускает это событие, когда форма недействительна, в результате чего пользователь никогда не сможет щелкнуть ее снова.(IE8 не отправляет форму, но событие запускается.)

Я попытался прикрепить функцию к событию нажатия кнопки отправки.Там я отключил кнопку отправки, показал значок ожидания и получил следующее:

$('[data-app-form-submit-button="true"]').live('click', function (e) {
    var form = $(this).parents('form');
    var icon = form.find('[data-app-form-submitting-icon="true"]');
    icon.show();
    $(this).attr('disabled', 'disabled');
    $.ajaxSetup({ async: false });
    var isValid = form.valid();
    $.ajaxSetup({ async: true });
    alert(isValid);
});

Проблема в том, что вызов установки ajax на самом деле не отключает асинхронный вызов.Это происходит, если я перемещаю его из функции щелчка, но затем отключает асинхронность для всего.Вместо этого на странице сразу появляется предупреждение «true», что проверяется путем установки точки останова для метода действия удаленной проверки.

Есть идеи?

Дополнительное примечание:

Я забыл упомянуть, что в IE8 событие submit вызывается только тогда, когда рассматриваемое текстовое поле не проходит проверку, которая может произойти на клиенте.Например, если не удается выполнить обязательное или регулярное выражение, submit () запускается.Для метода действия удаленной проверки он не запускается.Однако, как только он не проходит проверку клиента, последующие удаленные проверки также инициируют событие отправки IE8.

Ответ Рассу Кэму (комментарий № 1)

Вотсоответствующий код в модели представления:

public class SignUpForm : IValidatableObject
{
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email Address")]
    [Required(ErrorMessage = "Email Address is required.")]
    [RegularExpression(@"^(email regex here)$",
        ErrorMessage = "This is not a valid email address.")]
    [Remote("Validate", "ControllerName", "AreaName", HttpMethod = "POST")]
    public string EmailAddress { get; set; }

    public IEnumerable<ValidationResult> Validate(
        ValidationContext validationContext)
    {

Я рад, что вы заставили меня взглянуть на визуализированный <form>.Тег формы и элементы ввода выглядят так:

<form action="/post-action-method" method="post" novalidate="novalidate">
...
<input class="text-box single-line" data-app-focus="true" data-val="true" 
    data-val-regex="This is not a valid email address." 
    data-val-regex-pattern="^(email regex here)$" 
    data-val-remote="&amp;#39;Email Address&amp;#39; is invalid." 
    data-val-remote-additionalfields="*.EmailAddress" 
    data-val-remote-type="POST" 
    data-val-remote-url="/validate-action-method" 
    data-val-required="Email Address is required." 
    id="EmailAddress" name="EmailAddress" type="text" value=""> 
 ... 
<input type="submit" value="Submit this form" 
    data-app-form-submit-button="true" />

До сих пор я никогда не видел атрибут novalidate = "novalidate".Вот как это выглядит в файле cshtml:

@using (Html.BeginForm())
{
    @Html.EditorForModel()
    @Html.AntiForgeryToken("assault")
}

Я также использую токен против подделки, если это имеет значение.Спасибо.

Ответы [ 4 ]

3 голосов
/ 20 октября 2011

Это вроде хаки, но я бы предложил попробовать следующее.

Сначала скройте кнопку отправки с помощью display="none" и покажите собственную кнопку «Отправить», которая запускает ваш скрипт выше.

Во-вторых, на своей странице добавьте флаг var [var remotePending = false;] и переменную для вызова setInterval [var intervalPending;], и в своем скрипте установите флаг в значение true, а затем вызовите следующую функцию, используя intervalPending = setInterval('remoteCheck()', 200);

function remoteCheck() {
    if ($.validator.pendingRequest == 0) {
        // requests are done
        // clear interval
        clearInterval(intervalPending);
        // re-enable our "submit" button

        // "click" the hidden button
        $("#hiddenSubmit").click();
    }
    // we will try again after the interval passes
}

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

2 голосов
/ 24 мая 2012

Я немного опоздал с этим, но наткнулся на этот вопрос, пытаясь решить подобную проблему.Я тоже не хотел использовать Interval, поэтому я придумал другое решение и подумал, что, возможно, здесь стоит рассказать об этом другим.

В конце я решил переопределить методы startRequest и stopRequest валидатора jQuery, чтобы добавить свою собственную логику.После выполнения своей собственной логики я просто вызываю старые методы валидатора.

// Extend jQuery validator to show loading gif when making remote requests
var oldStartRequest = $.validator.prototype.startRequest;
$.validator.prototype.startRequest = function (element) {
    var container = $('form').find("[data-valmsg-for='" + element.name + "']");
    container.addClass('loading');       

    oldStartRequest.apply(this, arguments);
};

var oldStopRequest = $.validator.prototype.stopRequest;
$.validator.prototype.stopRequest = function (element) {
    var container = $('form').find("[data-valmsg-for='" + element.name + "']");
    container.removeClass('loading');

    oldStopRequest.apply(this, arguments);
};

Все, что я хотел сделать для своих целей, это просто добавить класс css 'loading' в смежное поле сообщения проверки, чтобы показатьзагрузка GIF, но вы можете легко расширить это, чтобы включить / отключить кнопку и т. д.

1 голос
/ 20 января 2012

Я обнаружил, что озадачен этой прошлой ночью, и после попытки различных подходов, я получил эволюцию консультеллорбенов.Так как counsellorbens не работали прямо из коробки, я подумала, что поделюсь этим, чтобы у других не было такой же головной боли.Это не такое «чистое» решение, как хотелось бы (я действительно ненавижу использовать интервалы).Но, кажется, этого достаточно.

var iIntervalId = null;

//
// DECLARE FUNCTION EXPRESSIONS
//

//==============================================================================
// function that triggers update when remote validation completes successfully
//==============================================================================
var fnPendingValidationComplete = function () {

  var validator = $("#frmProductType").data("validator");
  if (validator.pendingRequest === 0) {

    clearInterval(iIntervalId);

    //Force validation to present to user (this will not retrigger remote validation)
    if ($("#frmProductType").valid()) {

      alert("valid - you can submit now if you like");

    }
    //else { alert("invalid"); }
  }
  //else { alert("NOT YET"); }
},

//==============================================================================
// Trigger validation
//==============================================================================
fnTriggerValidation = function (evt) {

  //Remove any cached values to ensure that remote validation is retriggered
  $("#txtProductType").removeData("previousValue");

  //Trigger validation
  $("#frmProductType").valid();

  //Setup interval which will evaluate validation (this approach because of remote validation)
  iIntervalId = setInterval(fnPendingValidationComplete, 50);
};

fnTriggerValidation();
0 голосов
/ 22 октября 2011

Я решил эту проблему, но кнопка отключения / ожидания показа изображения появляется только при наличии действительной отправленной формы.Это нормально, так как множественные неверные представления формы являются идемпотентными, пользователь может щелкнуть столько, сколько он хочет.(Кроме того, метод действия удаленной проверки кэшируется со значениями его параметров.)

$(function () {
    $('form').bind('invalid-form.validate', function () {
        $('form').each(function () {
            $(this).find(
                '[data-app-form-submitting-icon="true"]').hide();
            var button = $(this).find(
                'input[type="submit"][data-app-form-submit-button="true"]');
            setTimeout(function () {
                button.removeAttr('disabled');
            }, 1);
        });
    });
    $('form').live('submit', function (e) {
        $(this).find('[data-app-form-submitting-icon="true"]').show();
        var button = $(this).find(
            'input[type="submit"][data-app-form-submit-button="true"]');
        setTimeout(function () {
            button.attr('disabled', 'disabled');
        }, 0);
    });
});

Это тоже немного странно, но когда я не использовал setTimeout, действие submit никогда не запускало неверный обработчик..

...