Отключить кнопку при отправке формы

У меня есть кнопка, которую я хотел бы отключить при отправке формы, чтобы пользователь не мог отправить ее несколько раз.

Я попытался наивно отключить кнопку с помощью javascript onclick, но затем, если проверка на стороне клиента не удалась, кнопка останется отключенной.

Как отключить кнопку, когда форма успешно отправляется, а не только когда пользователь нажимает?

Это форма ASP.NET, поэтому я хотел бы по возможности подключиться к жизненному циклу ajax-страницы asp.net.

16 ответов

Решение

Дайте этому вихрь:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

         // Identify button as a "disabled-when-clicked" button...
         WebHelpers.DisableButtonOnClick( buttonTest, "showPleaseWait" ); 
    }

    protected void buttonTest_Click( object sender, EventArgs e )
    {
        // Emulate a server-side process to demo the disabled button during
        // postback.
        Thread.Sleep( 5000 );
    }
}



using System;
using System.Web;
using System.Web.UI.WebControls;
using System.Text;

public class WebHelpers
{
    //
    // Disable button with no secondary JavaScript function call.
    //
    public static void DisableButtonOnClick( Button ButtonControl )
    {
        DisableButtonOnClick( ButtonControl, string.Empty );    
    }

    //
    // Disable button with a JavaScript function call.
    //
    public static void DisableButtonOnClick( Button ButtonControl, string ClientFunction )
    {   
        StringBuilder sb = new StringBuilder( 128 );

        // If the page has ASP.NET validators on it, this code ensures the
        // page validates before continuing.
        sb.Append( "if ( typeof( Page_ClientValidate ) == 'function' ) { " );
        sb.Append( "if ( ! Page_ClientValidate() ) { return false; } } " );

        // Disable this button.
        sb.Append( "this.disabled = true;" ); 

        // If a secondary JavaScript function has been provided, and if it can be found,
        // call it. Note the name of the JavaScript function to call should be passed without
        // parens.
        if ( ! String.IsNullOrEmpty( ClientFunction ) ) 
        {
            sb.AppendFormat( "if ( typeof( {0} ) == 'function' ) {{ {0}() }};", ClientFunction );  
        }

        // GetPostBackEventReference() obtains a reference to a client-side script function 
        // that causes the server to post back to the page (ie this causes the server-side part 
        // of the "click" to be performed).
        sb.Append( ButtonControl.Page.ClientScript.GetPostBackEventReference( ButtonControl ) + ";" );

        // Add the JavaScript created a code to be executed when the button is clicked.
        ButtonControl.Attributes.Add( "onclick", sb.ToString() );
    }
}

Я не большой поклонник написания всего этого javascript в коде позади. Вот как выглядит мое окончательное решение.

Кнопка:

<asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClick="btnSubmit_Click" OnClientClick="doSubmit(this)" />

Javascript:

<script type="text/javascript"><!--
function doSubmit(btnSubmit) {
    if (typeof(Page_ClientValidate) == 'function' && Page_ClientValidate() == false) { 
        return false;
    }    
    btnSubmit.disabled = 'disabled';
    btnSubmit.value = 'Processing. This may take several minutes...';
    <%= ClientScript.GetPostBackEventReference(btnSubmit, string.Empty) %>;    
}
//-->
</script>

Следующая функция полезна без необходимости в отключающей части, которая, как правило, ненадежна. Просто используйте "return check_submit();" как часть обработчика onclick кнопок отправки.

Также должно быть скрытое поле для хранения начального значения form_submitted, равного 0;

<input type="hidden" name="form_submitted" value="0">

function check_submit (){
            if (document.Form1.form_submitted.value == 1){
                alert("Don't submit twice. Please wait.");
                return false;
            }
            else{
                document.Form1.form_submitted.value = 1;
                return true;
            }
            return false;
    }

Отключите кнопку в самом конце вашего обработчика отправки. Если проверка не пройдена, она должна вернуть false до этого.

Тем не менее, подход JavaScript не является чем-то, на что можно положиться, поэтому у вас должно быть что-то, чтобы обнаружить дубликаты и на сервере.

Если проверка прошла успешно, отключите кнопку. если нет, то не надо.

function validate(form) {
  // perform validation here
  if (isValid) {
    form.mySubmitButton.disabled = true;
    return true;
  } else {
    return false;
  }
}

<form onsubmit="return validate(this);">...</form>

Установите видимость на кнопке "нет";


btnSubmit.Attributes("onClick") = document.getElementById('btnName').style.display = 'none';

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

Правильный (по крайней мере, в отношении удобства использования) способ состоит в том, чтобы отключить кнопку с помощью атрибута OnClientClick, выполнить проверку на стороне клиента, а затем использовать полученный результат для продолжения или повторного включения кнопки.

Конечно, вы должны ТАКЖЕ написать для этого код на стороне сервера, так как вы не можете полагаться на проверку, даже если она выполняется из-за отсутствия или конкретной реализации JavaScript. Однако, если вы полагаетесь на сервер, управляющий состоянием кнопки "включено / выключено", то в любом случае у вас нет возможности заблокировать отправку формы несколько раз. По этой причине у вас должна быть какая-то логика для обнаружения нескольких представлений от одного и того же пользователя за короткий промежуток времени (например, идентичные значения из одного сеанса).

Обратите внимание, что подход rp дважды отправит вашу форму, если вы используете кнопки с UseSubmitBehavior="false",

Я использую следующий вариант кода RP:

public static void DisableButtonOnClick(Button button, string clientFunction)
{
    // If the page has ASP.NET validators on it, this code ensures the
    // page validates before continuing.
    string script = "if (typeof(Page_ClientValidate) == 'function') { "
            + "if (!Page_ClientValidate()) { return false; } } ";

    // disable the button
    script += "this.disabled = true; ";

    // If a secondary JavaScript function has been provided, and if it can be found, call it.
    // Note the name of the JavaScript function to call should be passed without parens.
    if (!string.IsNullOrEmpty(clientFunction))
        script += string.Format("if (typeof({0}) == 'function') {{ {0}() }} ", clientFunction);

    // only need to post back if button is using submit behaviour
    if (button.UseSubmitBehavior)
        script += button.Page.GetPostBackEventReference(button) + "; ";

    button.Attributes.Add("onclick", script);
}

Обнаружил код rp в нашем устаревшем приложении, которое боролось с каким-то сумасшедшим поведением.

Отследил это до странной комбинации срабатывания события - когда DisableButtonOnClick() использовался на кнопке asp внутри UpdatePanel, POST будет отправлен дважды (один раз doPostBack, добавленным DisableButtonOnClick(), и один раз UpdatePanel). Однако это произошло только с некоторыми браузерами (ранние версии Edge, но не последние, и IE11 сделал это, Chrome и FireFox нет (по крайней мере, версии, с которыми я тестировал)). Я предполагаю, что Chrome и более новые версии Edge каким-то образом справляются с этим сценарием. Отслеживание проблемы с помощью F12 devtools в IE - два POST происходят так близко друг к другу, что первый сразу же АБОРТИРУЕТСЯ, но при некоторых условиях (задержка в сети, загрузка пользовательского компьютера и т. Д.) Запрос доходит до сервера раньше, чем браузер прервать.Таким образом, это приводит к кажущимся случайным двойным сообщениям, возникающим из-за нажатия кнопок по всей системе, и отследить это было сложно. Исправление состоит в том, чтобы добавить "return false"; после doPostBack, чтобы предотвратить включение UpdatePanel, когда используются старые браузеры.

TL; DR - остерегайтесь этого кода на кнопках в панелях обновлений. Это хороший подход и хороший метод, но в моем (вероятном крайнем) случае есть потенциальная проблема.

ps - Я бы прокомментировал пост rp, но у меня нет репутации. Думаю, это может быть полезно для будущих путешественников.

Только что услышал о свойстве "DisableOnSubmit" , вот так:

<asp:Button ID="submit" runat="server" Text="Save"
    OnClick="yourClickEvent" DisableOnSubmit="true" />

При визуализации атрибут кнопки onclick выглядит так:

onclick="this.disabled=true; setTimeout('enableBack()', 3000);
  WebForm_DoPostBackWithOptions(new
  WebForm_PostBackOptions('yourControlsName', '', true, '', '', false, true))

А функция JavaScript enableBack() выглядит следующим образом:

function enableBack()
{
    document.getElementById('yourControlsName').disabled=false;
}

Поэтому, когда кнопка нажата, она отключается на 3 секунды. Если форма публикуется успешно, вы никогда не увидите кнопку повторного включения. Однако, если какие-либо валидаторы не сработали, кнопка снова станет активной через 3 секунды.

Все это просто путем установки атрибута на кнопку - никакой код JavaScript не должен быть написан от руки.

Одно из моих решений заключается в следующем:

добавьте скрипт в page_load вашего файла aspx

    HtmlGenericControl includeMyJava = new HtmlGenericControl("script");
    includeMyJava.Attributes.Add("type", "text/javascript");
    includeMyJava.InnerHtml = "\nfunction dsbButton(button) {";
    includeMyJava.InnerHtml += "\nPage_ClientValidate();";
    includeMyJava.InnerHtml += "\nif(Page_IsValid)";
    includeMyJava.InnerHtml += "\n{";
    includeMyJava.InnerHtml += "\nbutton.disabled = true;";
    includeMyJava.InnerHtml += "}";
    includeMyJava.InnerHtml += "\n}";
    this.Page.Header.Controls.Add(includeMyJava);

а затем установите параметры кнопки aspx следующим образом:

<asp:Button ID="send" runat="server" UseSubmitBehavior="false" OnClientClick="dsbButton(this);" Text="Send" OnClick="send_Click" />

Обратите внимание, что "onClientClick" помогает отключить кнопку, а "UseSubmitBehaviour" отключает традиционное поведение отправки страницы и позволяет asp.net отображать поведение отправки в пользовательском сценарии.

удачи

-Вакас Аслам

Так что простое отключение кнопки через javascript не является кросс-браузерной совместимой опцией. Chrome не будет отправлять форму, если вы просто используете OnClientClick="this.disabled=true;"
Ниже приведено решение, которое я протестировал в Firefox 9, Internet Explorer 9 и Chrome 16:

<script type="text/javascript">
var buttonToDisable;
function disableButton(sender)
{
    buttonToDisable=sender;
    setTimeout('if(Page_IsValid==true)buttonToDisable.disabled=true;', 10);
}
</script>

Затем зарегистрируйте "disableButton" с помощью события click для кнопки отправки формы, одним из следующих способов:

<asp:Button runat="server" ID="btnSubmit" Text="Submit" OnClientClick="disableButton(this);" />

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

Основываясь на ответе @rp., Я изменил его, чтобы вызвать пользовательскую функцию и либо отправить и отключить в случае успеха, либо "остановить" при ошибке:

public static void DisableButtonOnClick(Button ButtonControl, string ClientFunction)
{
    StringBuilder sb = new StringBuilder(128);

    if (!String.IsNullOrEmpty(ClientFunction))
    {
        sb.AppendFormat("if (typeof({0}) == 'function') {{ if ({0}()) {{ {1}; this.disabled=true; return true; }} else {{ return false; }} }};", ClientFunction, ButtonControl.Page.ClientScript.GetPostBackEventReference(ButtonControl, null));
    }
    else
    {
        sb.Append("return true;");
    }

    ButtonControl.Attributes.Add("onclick", sb.ToString());
}

Решением будет установка скрытого поля при нажатии кнопки с номером 1.

В обработчике нажатия кнопки первым делом нужно проверить это число, если оно не равно 1, просто выйти из функции.

Вы также можете воспользоваться преимуществами события javascript onsubmit (), которое доступно в формах. Это событие возникает, когда форма фактически отправляется, и не должно прерываться до тех пор, пока проверка не будет завершена.

Это более простой, но похожий метод, чем тот, что предложил rp:

function submit(button) {
        Page_ClientValidate(); 
        if(Page_IsValid)
        {
            button.disabled = true;
        }
}

 <asp:Button runat="server" ID="btnSubmit" OnClick="btnSubmit_OnClick" OnClientClick="submit(this)" Text="Submit Me" />

Не уверен, поможет ли это, но есть событие отправки в форме. Вы можете использовать это событие при отправке формы (с любой кнопки или элементов управления). Для справки: http://www.htmlcodetutorial.com/forms/_FORM_onSubmit.html

Другие вопросы по тегам