フォーム送信時のボタンを無効にする
-
01-07-2019 - |
質問
ユーザーが複数回送信するのを防ぐために、フォームの送信時に無効にしたいボタンがあります。
JavaScript onclickでボタンを単純に無効にしようとしましたが、クライアント側の検証が失敗した場合、ボタンは無効のままになります。
ユーザーがクリックしたときだけでなく、フォームが正常に送信されたときにボタンを無効にするにはどうすればよいですか?
これは ASP.NET フォームなので、可能であれば、asp.net ajax ページのライフサイクルにうまく接続したいと考えています。
解決
これを試してみてください:
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();」を使用するだけです送信ボタンのオンクリックハンドラーの一部として。
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';
二重送信を防ぐだけでなく、ボタンを複数回押したくないことをユーザーに明確に示します。
これが役立つかどうかはわかりませんが、フォームには onsubmit イベントがあります。このイベントは、フォームが送信されるたびに (任意のボタンまたはコントロールから) 使用できます。参考のために: http://www.htmlcodetutorial.com/forms/_FORM_onSubmit.html
解決策は、ボタンをクリックしたときに非表示フィールドに番号 1 を設定することです。
ボタンのクリック ハンドラーで最初に行うことは、関数から返される数値が 1 以外であるかどうかを確認することです。
フォームで使用できる onsubmit() JavaScript イベントを利用することもできます。このイベントは、フォームが実際に送信されるときに発生し、検証が完了するまでトラップされません。
これはより簡単ですが似た方法です。 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" />
ボタンを使用している場合、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 の欠如または特定の実装が原因で実行される検証に依存することはできないため、このためのサーバー側のコードも記述する必要があります。ただし、ボタンの有効/無効状態を制御するサーバーに依存している場合は、基本的に、フォームを複数回送信するユーザーをブロックする方法がありません。このため、短期間に同じユーザーからの複数の送信 (たとえば、同じセッションからの同一の値) を検出するための何らかのロジックが必要です。
私の解決策の1つは次のとおりです。
aspx ファイルの page_load にスクリプトを追加します
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 がユーザー スクリプトで送信動作をレンダリングできるようにすることに注意してください。
幸運を
-ワカス・アスラム
次のような <asp:Button> の "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))
「enableBack()」JavaScript 関数は次のようになります。
function enableBack()
{
document.getElementById('yourControlsName').disabled=false;
}
したがって、ボタンをクリックすると、3 秒間無効になります。フォームが正常に投稿された場合、ボタンが再度有効になることはありません。ただし、バリデーターが失敗した場合、ボタンは 3 秒後に再び有効になります。
これらはすべて、ボタンに属性を設定するだけで実行できます。JavaScript コードを手動で記述する必要はありません。
したがって、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」を登録します。1 つの方法は次のとおりです。
<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());
}