У меня есть кнопка, которую я хотел бы отключить при отправке формы, чтобы пользователь не отправлял ее несколько раз.
Я попытался наивно отключить кнопку с помощью javascript onclick, но затем, если проверка на стороне клиента не выполняется, кнопка остается отключенной.
Как отключить кнопку, если форма успешно отправляется не только при нажатии пользователем?
Это форма ASP.NET, поэтому я хотел бы, если возможно, хорошо подключиться к жизненному циклу страницы asp.net ajax.





Отключите кнопку в самом конце обработчика отправки. Если проверка не удалась, перед этим она должна вернуть false.
Однако подход JavaScript не является чем-то, на что можно положиться, поэтому у вас также должно быть что-то для обнаружения дубликатов на сервере.
Не уверен, что это поможет, но в форме есть событие onsubmit. Вы можете использовать это событие всякий раз, когда форма отправляется (с любой кнопки или элементов управления). Для справки: http://www.htmlcodetutorial.com/forms/_FORM_onSubmit.html
Следующая функция полезна без необходимости отключения части, которая имеет тенденцию быть ненадежной. Просто используйте "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;
}
Решением будет установка скрытого поля при нажатии кнопки с номером 1.
В обработчике нажатия кнопки первое, что нужно сделать, это проверить это число, если это что-то иное, чем 1, просто вернитесь из функции.
Вы также можете воспользоваться событием javascript onsubmit (), которое доступно в формах. Это событие возникает, когда форма действительно отправляется, и не должно прерываться до завершения проверки.
Дайте этому кружку:
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() );
}
}
рп. одно небольшое изменение, которое мне пришлось сделать, - передать имя моей группы проверки методу Page_ClientValidate (). Спасибо за код!
Я не злодей ... но писать столько кода вместо onsubmit = "this.button.disable = true" или чего-то подобного в теге <form> - это как-то ... странно? : |
Staicu: ваше решение не принимает во внимание, прошла ли проверка или нет. В вашем решении, если проверка не удалась, кнопка сохранения остается отключенной.
Кажется, для меня Брауни принимает во внимание валидацию.
Отличный фрагмент кода какое-то время искал что-то подобное
Отличный код, в итоге я сделал его методом расширения для всех своих кнопок. public static void DisableButtonOnClick (эта кнопка ButtonControl, строка ClientFunction)
50 строк кода на стороне сервера, необходимых для выполнения тонкости на стороне клиента? Спасибо, не надо!!
Дай парню передохнуть, Джош: некоторые из этих строк пусты, многие используют операторы и довольно много комментариев! :-)
Джош. Сейчас, когда я прочно закрепился за jQuery и большим объемом работы на стороне клиента, мой подход теперь может немного отличаться - но только потому, что теперь я меньше привязан к элементам управления на стороне сервера. Тем не менее, если LOC - ваша метрика, покажите мне клиентский код меньшим количеством кода! Обязательно поиграйте с валидаторами ASP.NET и вызовите функцию, если она предусмотрена. (спасибо за защиту, Стив Дж.)
отличная идея, кто-нибудь знает, как я могу добавить в это решение подтверждение возврата ('Вы уверены, что хотите отправить') {// выполнить обработку}?
Я нашел этот подход полезным, поскольку класс WebHelper позволяет легко использовать его повторно. Первоначально подход ниже (меньше кода программной части JS) казался приятным и простым, но у меня были проблемы с его проверкой. (Если проверка не удалась, кнопка НЕ вернется в активное состояние надежно.) Таким образом, эта кнопка оказалась победителем. (Особенно, если вы работаете над тяжелым серверным проектом.)
если проверка прошла успешно, отключите кнопку. если нет, то не надо.
function validate(form) {
// perform validation here
if (isValid) {
form.mySubmitButton.disabled = true;
return true;
} else {
return false;
}
}
<form onsubmit = "return validate(this);">...</form>
Это более простой, но похожий метод, чем то, что предлагает 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" />
Установите для кнопки видимость «нет»;
btnSubmit.Attributes("onClick") = document.getElementById('btnName').style.display = 'none';Это не только предотвращает двойную отправку, но и является четким индикатором для пользователя, что вы не хотите, чтобы кнопка нажималась более одного раза.
... хотя я предпочитаю использовать атрибут OnClientClick, а не код программной части.
... и разве вам не нужно, чтобы он не исчезал, если проверка на стороне клиента не удалась?
Я не большой поклонник написания всего этого 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>
Только что слышал о свойстве DisableOnSubmit элемента <asp: Button>, например:
<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 не нужно писать вручную.
Это было бы здорово, но в моей версии ASP.NET этого нет. Какую версию ты используешь!?
В то время я использовал последнюю версию: Visual Studio 2008. Я больше не работаю на этого работодателя, поэтому я не могу проверить что-либо еще (пакеты обновлений, версию среды выполнения .NET и т. д.). Приносим извинения за задержку с ответом!
Теперь, когда я думаю об этом, я считаю, что на странице использовался AJAX, так что это могло быть расширением, предоставленным набором инструментов.
Обратите внимание, что подход 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);
}
Правильный (по крайней мере, с точки зрения удобства использования) способ - отключить кнопку с помощью атрибута OnClientClick, выполнить проверку на стороне клиента, а затем использовать результат этого для продолжения или повторного включения кнопки.
Конечно, вы должны ТАКЖЕ написать для этого код на стороне сервера, поскольку вы не можете полагаться на проверку, даже если она выполняется из-за отсутствия или конкретной реализации 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 отображать поведение отправки в соответствии с пользовательским скриптом.
удачи
-Waqas Aslam
Поэтому простое отключение кнопки с помощью 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 с событием щелчка кнопки отправки формы, один из способов:
<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());
}
Обнаружил код 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, но у меня нет репутации. Подумал, что это может быть полезно для будущих путешественников.
Здесь много отличных ответов, но этот красивый.