Почему моя форма не публикуется, когда я отключаю кнопку отправки, чтобы предотвратить двойной щелчок?
Как и у любого другого веб-разработчика на планете, у меня есть проблема с пользователями, дважды щелкающими по кнопке "Отправить" в моих формах. Насколько я понимаю, обычным способом решения этой проблемы является отключение кнопки сразу после первого щелчка, однако, когда я делаю это, она не публикуется.
Я провел некоторое исследование по этому вопросу, бог знает, что информации достаточно, но другие вопросы, такие как кнопка "Отключить" при отправке формы, отключение кнопки, похоже, работают. Исходный плакат кнопки "Отключить после отправки", похоже, имел ту же проблему, что и я, но нет упоминания о том, как / если он решил ее.
Вот некоторый код о том, как это повторить (протестировано в IE8 Beta2, но с той же проблемой в IE7)
Мой код aspx
<%@ Page Language="C#" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<script language="javascript" type="text/javascript">
function btn_onClick()
{
var chk = document.getElementById("chk");
if(chk.checked)
{
var btn = document.getElementById("btn");
btn.disabled = true;
}
}
</script>
<body>
<form id="form1" runat="server">
<asp:Literal ID="lit" Text="--:--:--" runat="server" />
<br />
<asp:Button ID="btn" Text="Submit" runat="server" />
<br />
<input type="checkbox" id="chk" />Disable button on first click
</form>
</body>
</html>
Мой код cs
using System;
public partial class _Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
btn.Click += new EventHandler(btn_Click);
btn.OnClientClick = "btn_onClick();";
}
void btn_Click(object sender, EventArgs e)
{
lit.Text = DateTime.Now.ToString("HH:mm:ss");
}
}
Обратите внимание, что при нажатии кнопки происходит обратная передача, и время обновляется. Но когда вы устанавливаете флажок, при следующем нажатии кнопки кнопка отключается (как и ожидалось), но никогда не выполняет обратную передачу.
ЧТО, ЧЕРТ, Я ЗДЕСЬ ЗДЕСЬ???
Заранее спасибо.
11 ответов
Я думаю, что вы просто пропустите этот тег:
UseSubmitBehavior="false"
Попробуйте это так:
<asp:Button ID="btnUpdate" runat="server" UseSubmitBehavior="false" OnClientClick="if(Page_ClientValidate()) { this.disabled = true; } else {return false;}" Text = "Update" CssClass="button" OnClick="btnUpdate_Click" ValidationGroup="vgNew"/>
UseSubmitBehavior="false"
преобразует кнопку отправки в обычную кнопку (<input type="button">
). Если вы не хотите, чтобы это произошло, вы можете скрыть кнопку отправки и немедленно вставить отключенную кнопку на ее место. Поскольку это происходит так быстро, это выглядит как отключение кнопки для пользователя. Подробности в блоге Джоша Стодола.
Пример кода (jQuery):
$("#<%= btnSubmit.ClientID %>").click(function()
{
$(this)
.hide()
.after('<input type="button" value="Please Wait..." disabled="disabled" />');
});
fallen888 прав, ваш подход не работает кросс-браузер. Я использую этот маленький фрагмент, чтобы предотвратить двойной щелчок.
"Отключение" элементов управления HTML не всегда приводит к согласованному поведению во всех основных браузерах. Поэтому я стараюсь не делать этого на стороне клиента, потому что (работая с моделью ASP.NET) вам необходимо отслеживать состояние элемента на клиенте и сервере в этом случае.
Я бы переместил кнопку с видимой части окна, переключив className кнопки на класс CSS, который содержит следующее:
.hiddenButton
{
position: absolute;
top: -1000px;
left: -1000px;
}
Теперь, что поставить вместо кнопки?
- Либо изображение, которое выглядит как отключенная кнопка
- Или просто текст, который говорит: "Пожалуйста, подождите..."
И это можно сделать так же, но в обратном порядке. Начните с того, что элемент скрывается при загрузке страницы, а затем переключитесь на видимое имя класса при отправке формы.
Мы используем следующий скрипт JQuery, чтобы отключить все кнопки (тип ввода = отправить и кнопка), когда нажата одна кнопка.
Мы просто включили скрипт в глобальный файл JavaScript, поэтому нам не нужно ничего запоминать при создании новых кнопок.
$(document).ready(function() {
$(":button,:submit").bind("click", function() {
setTimeout(function() {
$(":button,:submit").attr("disabled", "true");
}, 0);
});
});
Этот скрипт может быть легко расширен проверкой Page_ClientValidate().
Это правильный и простой способ сделать это:
Работает во всех браузерах (в отличие от принятого решения выше).
Создайте вспомогательный метод в вашем приложении (скажем, в пространстве имен Utlity):
Public Shared Sub PreventMultipleClicks(ByRef button As System.Web.UI.WebControls.Button, ByRef page As System.Web.UI.Page)
button.Attributes.Add("onclick", "this.disabled=true;" + page.ClientScript.GetPostBackEventReference(button, String.Empty).ToString)
End Sub
Теперь из кода каждой из ваших веб-страниц вы можете просто позвонить:
Utility.PreventMultipleClicks(button1, page)
где button1 - это кнопка, которую вы хотите предотвратить несколькими нажатиями.
Это просто устанавливает обработчик нажатия на: this.disabled = true
а затем добавляет кнопки собственного обработчика постов назад, так что мы получаем:
OnClick="this.disabled= истина";__doPostBack('ID$ID','');"
Это не нарушает поведение страницы по умолчанию и работает во всех браузерах, как и ожидалось.
Наслаждайтесь!
document.getElementById('form1').onsubmit = function() {
document.getElementById('btn').disabled = true;
};
ПОЛЬЗОВАТЕЛЯМ JQUERY
Вы столкнетесь со всевозможными проблемами, пытаясь добавить javascript непосредственно к событию onClick на кнопках ASP.NET при использовании прослушивателей событий jQuery.
Я нашел лучший способ отключить кнопки и заставить работать обратную передачу - сделать что-то вроде этого:
$(buttonID).bind('click', function (e) {
if (ValidateForm(e)) {
//client side validation ok!
//disable the button:
$(buttonID).attr("disabled", true);
//force a postback:
try {
__doPostBack($(buttonID).attr("name"), "");
return true;
} catch (err) {
return true;
}
}
//client side validation failed!
return false;
});
Где ValidateForm - ваша пользовательская функция проверки, которая возвращает истину или ложь, если ваша форма проверяет сторону клиента.
И buttonID - это идентификатор вашей кнопки, такой как "#button1"
Можно также попробовать следующий способ предотвратить двойное нажатие кнопки «ОТПРАВИТЬ»:
ОБЪЯСНЕНИЕ (в порядке появления кода выше):
- CSS: обрабатывает элемент счетчика, используемый как часть тега значка в замененной кнопке.
- Добавление библиотеки значков в заголовок обязательно , если вы хотите использовать класс значков fa-spinner.
- В теге скрипта вызывается метод Validate для проверки заполнения всех обязательных элементов формы перед нажатием кнопки отправки.
- После успешной проверки я скрываю кнопку отправки [.hide()] и заменяю ее другой кнопкой [.after()].
- Установка свойства DISABLED для новой кнопки является обязательной, иначе она будет работать как активная кнопка.
ПРИМЕЧАНИЕ. Я использовал кнопку для замены кнопки отправки. Но вы можете использовать текст ввода или любой другой подходящий элемент в соответствии с вашими требованиями.
Убедитесь, что ваша функция javascript возвращает true (или значение, которое будет оцениваться как логическое true), иначе форма не будет отправлена.
function btn_click()
var chk = document.getElementById("chk");
if(chk.checked)
{
var btn = document.getElementById("btn");
btn.disabled = true;
return true; //this enables the controls action to propagate
}
else return false; //this prevents it from propagating
}
Что будет в целях отладки, что произойдет, если вы положите предложение else против if(chk.checked)?