- 開発技術
ASP.netにおいて、TextBoxの中のDatePickerのtextchangedイベントが発生しない場合の対処法
- ASP.NET
- VB.NET
- JavaScript
TextBoxの中のコントコールはDatePickerの場合の現状
【エンジニア募集中】フルリモート可◎、売上/従業員数9年連続UP、平均残業8時間、有給取得率90%、年休124日以上 etc. 詳細はこちらから>
ASP.netで開発する際、TextBoxの中にDatePickerを設定すると、通常のtextを入力する場合と違い、textchangedイベントが発生しないことを確認できました。
イベントの発生順
TextBoxをクリックする際、イベントの発生順は下記通りです。
- focusout (TextBoxがフォーカスを失う直前)
- focusin(DatePickerコントロールがfocusを受け取る直前)
- blur(TextBoxがフォーカスを失った直後)
- focus(DatePickerがフォーカスを受け取った直後)
- focusout(DatePcikerがフォーカスを失う直前)
- focusin(DatePcikerで日付をクリックした後に、選択された日付がTextBoxに反映した直後)
実装したい仕様
A.日付は直接TextBoxに入力可能、フォーカスアウト後はyyyy/MM/ddに編集する。
B.日付を選び直す場合、画面の一部のコントロールをクリアする。
C.日付が変わらない場合、画面の再表示をしない。
D.日付の妥当性チェックを行う。実在しない日付が入力された場合、エラーメッセージを出す
E.日付の妥当性チェックでエラーがない場合、検索を行う、検索結果を画面のコントロールに表示する。
プロジェクトの共通ルールにより、DatePickerのフォーマット編集はフロント側で実装したい。
仕様B、Dはバックエンド側で実装したい。
課題
イベントフローの中のfocusoutイベントとblurイベントを着目します。仕様Cの日付が変わらない場合、画面の再表示をしない要件があり、普通のTextBoxなら、TextBoxの入力内容が変わる場合、Textchangedイベントが発生するため、TextChangedハンドラーで実現したいことを書けばよいですが、今回のように、TextBoxの中にDatePickerが設定され、Textchangedイベントは発生しません。そのため、仕様Cの実現が難しくなります。
解決方法
日付のフォーマット編集後、TextBoxに反映後、その日付を一旦変数①に格納する。
フロント側でfocusoutイベントとblurイベントのハンドラーを別々に設定する。
focusoutイベントはblurイベントより前に発生するため、まず、focusoutイベントでは、yyyy/MM/ddフォーマット編集を行う。
blurイベントでは、TextBoxの中身と変数①と比較し、一致しない場合、バックエンド側にイベントハンドラーに渡す。
フロント側のjsの関連ソースの抜粋:
1 2 3 4 5 6 7 8 9 10 11 12 |
function dateFocusOut() { var newDate = txtDate.val(); if (newDate !== $("#変数①").val()) { __doPostBack('dateFocusOut', newDate); } } txtDate.blur(function () { dateFocusOut(); }); txtDate.focusout(function () { $(this).val(convertDateFormat($(this).val())); }); |
バックエンド側のソースの抜粋:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Try If IsPostBack Then If Request.Params.Keys.Cast(Of String)().Contains("__EVENTTARGET") Then Dim strEventTarget As String = Request.Params.Get("__EVENTTARGET") If strEventTarget = ("dateFocusOut") Then Dim newDate As String = Request.Params.Get("__EVENTARGUMENT") '日付フォーカスアウト TxtDate_DateChanged(sender, e, newDate) Return End If End If Else ‘処理を省略 End If Catch ex As Exception 'エラーページへ遷移する Finally '処理を省略 End Try End Sub Protected Sub TxtDate_TextChanged(sender As Object, e As EventArgs, newDate As String) Try 'メッセージエリアをクリアする Me.msg.delMessage() Dim msgList As List(Of String) = Nothing CommonInputCheck.InputCheckDate(Me.txtDate, "日付", True, msgList, mMasterPage.db) If msgList Is Nothing Then If Not String.IsNullOrEmpty(Me.txtDate.Text) And CommonInputCheck.InputCheckDate(Me.txtDate, "日付", True, msgList, Me.mMasterPage.db) Then Me.msg.delMessage() If newDate <> 変数① Then Me.mGridData.Clear() ‘対象画面項目をクリアする End If End If Else '実在しない日付の場合、エラーメッセージ表示する。 Me.msg.setMessage(msgList) End If ‘変数①に新しい日付をセットする 変数① = txtDate.Text Catch ex As Exception 'エラーページへ遷移する End Try End Sub |
上記のように、フロント側とバックエンド側のそれぞれの処理を連携することでtextchangedイベントハンドラー類似な機能を実現できました。
【エンジニア募集中】フルリモートも◎(リモート率85.7%)、平均残業8時間、年休124日以上、有給取得率90% etc. 詳細はこちらから>