Validator עבור שדות תאריך לידה

נוסף ב-07/06/2008 01:45 על ידי דניאל כץ
(Birth date fields validator)

נשאלה השאלה, איך אני מאגד את שלשת השדות של תאריך הלידה (יום, חודש ושנה) לערך אחד עבור ואלידציה (Validation)?

במצב הקיים, צריך להשתמש בשלש ואלידאטורים (Validators) מסוג RequiredFieldValidator ועוד 3 מסוג RangeValidator עבור טווח הערכים (למשל ימי החודש הם מ1 עד 31), וכל זה עדיין לא יעזור אם נרצה לבדוק טווח עבור כל התאריך בשלמות ולא עבור כל חלק שלו בנפרד. לפתרון לבעיה זו כתבתי WebControl שיורש מ – BaseCompareValidator בשם DateFieldsValidator.

DateFieldsValidator פותר את כל הבעיות שהזכרתי,

  • מכיל מאפיינים עבור 3 שדות (גם TextBoxים וגם DropDownListים ובעצם, כל דבר שנתמך ע"י הואלידאטורים הסטנדרטיים) אחד עבור כל חלק בתאריך
  • מכיל מאפיינים MinimumValue וMaximumValue לבדיקת טווח עבור התאריך בשלמותו.
  • לא תלוי בCulture מסויים (CultureInvariant).
  • מבצע וולידציה הן בצד לקוח (ללא רענון הדף), והן בצד שרת (במקרה שJavaScript מבוטל או לא נתמך בלקוח).
  • וכן תומך גם בכל הפיצ'רים האחרים של פקדי הואלידאציה הסטנדרטיים בFramework.

דוגמה לשימוש בואלידאטור:

    <table>
        <tr>
            <td>
                <asp:Label ID="Label3" runat="server" Text="Birth date:" />
            </td>
            <td>
                <asp:TextBox ID="txbDay" runat="server" MaxLength="2" />
                <asp:DropDownList ID="ddlMonth" runat="server">
                </asp:DropDownList>
                <asp:DropDownList ID="ddlYear" runat="server">
                </asp:DropDownList>
                <dk:DateFieldsValidator ID="DateFieldsValidator1" runat="server" 
                    DayToValidate="txbDay" MonthToValidate="ddlMonth" YearToValidate="ddlYear" 
                    MaximumValue="2000/1/1" MinimumValue="1999/1/1" >*</dk:DateFieldsValidator>
            </td>
        </tr>
    </table>

בכזה מקרה הקוד האחורי (Code behind) של הטופס ייראה כך:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 
        If Not IsPostBack Then
 
            For i As Integer = 1 To 12
                ddlMonth.Items.Add(New ListItem(New Date(2008, i, 1).ToString("MMMM"), i))
            Next
 
            ddlMonth.Items.Insert(0, New ListItem("---", -1) With {.Selected = True})
 
            For i As Integer = (Date.Now.Year - 120) To (Date.Now.Year - 8)
                ddlYear.Items.Add(New ListItem(i, i))
            Next
 
            ddlYear.Items.Insert(0, New ListItem("---", -1) With {.Selected = True})
 
        Else
 
            If Me.IsValid Then
 
                ' Do the right thing...
 
            End If
 
        End If
 
    End Sub

הקוד הזה מציג שדה טקסט (TextBox) אחד עבור היום בחודש, ושני שדות בחירה (DropDownList) עבור החודש והשנה. הקוד ממלא את רשימת האפשרויות לבחירה של כל אחד משדות הDropDownList בערכים המתאימים לחודשים ושנים כשלכל אחד מהאפשרויות (הListItems ליתר בהירות) יש גם ערך מספרי שאיתו לבסוף מתבצעת הואלידאציה. בנוסף בראש כל רשימה הוספתי "ערך סרק" שמקבל ערך מספרי שלילי ובכך מכשיל את הוולידציה במקרה שהמשתמש לא יבחר ערך אמיתי של חודש ושנה.

ליצירת ה DateFieldsValidator פתחתי פרויקט חדש מסוג ASP.NET Server Control, בחרתי ב DanielKatz.Web.UIכRoot Namespace של הפרוייקט ויצרתי 3 קבצים: DateFieldsValidator.vb, DateFieldsValidator.js, AssemblyInfo.vb. הנה הקוד שלהם:

DateFieldsValidator.vb

Imports System
Imports System.ComponentModel
Imports System.Globalization
Imports System.Text.RegularExpressions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Security.Permissions
 
<AspNetHostingPermission(SecurityAction.LinkDemand, Level:=AspNetHostingPermissionLevel.Minimal)> _
<AspNetHostingPermission(SecurityAction.InheritanceDemand, Level:=AspNetHostingPermissionLevel.Minimal)> _
<ToolboxData("<{0}:DateFieldsValidator runat=server />")> _
Public Class DateFieldsValidator
    Inherits BaseCompareValidator
 
#Region " Overriden Methods "
 
    Protected Overloads Overrides Sub AddAttributesToRender(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.Type = ValidationDataType.Date
        MyBase.SetFocusOnError = False
        MyBase.AddAttributesToRender(writer)
 
        If Me.RenderUplevel Then
            Dim maximumValue As String = Me.MaximumValue
            Dim minimumValue As String = Me.MinimumValue
 
            If minimumValue <> "" AndAlso maximumValue <> "" Then
                If MyBase.CultureInvariantValues Then
                    maximumValue = ConvertCultureInvariantToCurrentCultureFormat(maximumValue)
                    minimumValue = ConvertCultureInvariantToCurrentCultureFormat(minimumValue)
                End If
            End If
 
            Page.ClientScript.RegisterExpandoAttribute(ClientID, "evaluationfunction", "DateFieldsValidatorEvaluateIsValid")
            Page.ClientScript.RegisterExpandoAttribute(ClientID, "dayControl", MyBase.GetControlRenderID(Me.DayToValidate))
            Page.ClientScript.RegisterExpandoAttribute(ClientID, "monthControl", MyBase.GetControlRenderID(Me.MonthToValidate))
            Page.ClientScript.RegisterExpandoAttribute(ClientID, "yearControl", MyBase.GetControlRenderID(Me.YearToValidate))
            Page.ClientScript.RegisterExpandoAttribute(ClientID, "minimumValue", minimumValue)
            Page.ClientScript.RegisterExpandoAttribute(ClientID, "maximumValue", maximumValue)
        End If
    End Sub
 
    Protected Overloads Overrides Function ControlPropertiesValid() As Boolean
 
        If Me.DayToValidate.Trim().Length = 0 Then
            Throw New HttpException(String.Format("The DayToValidate property of {0} is empty.", Me.ID))
        End If
 
        If Me.MonthToValidate.Trim().Length = 0 Then
            Throw New HttpException(String.Format("The MonthToValidate property of {0} is empty.", Me.ID))
        End If
 
        If Me.YearToValidate.Trim().Length = 0 Then
            Throw New HttpException(String.Format("The YearToValidate property of {0} is empty.", Me.ID))
        End If
 
        MyBase.CheckControlValidationProperty(DayToValidate, "ControlsToValidate")
        MyBase.CheckControlValidationProperty(MonthToValidate, "MonthToValidate")
        MyBase.CheckControlValidationProperty(YearToValidate, "YearToValidate")
 
        If Me.MinimumValue <> "" OrElse Me.MaximumValue <> "" Then
            If Not BaseCompareValidator.CanConvert(MinimumValue, ValidationDataType.Date, MyBase.CultureInvariantValues) Then
                Throw New HttpException("Invalid formatted value in MinimumValue")
            End If
 
            If Not BaseCompareValidator.CanConvert(MaximumValue, ValidationDataType.Date, MyBase.CultureInvariantValues) Then
                Throw New HttpException("Invalid formatted value in MaximumValue")
            End If
 
            If BaseCompareValidator.Compare(MinimumValue, MyBase.CultureInvariantValues, MaximumValue, MyBase.CultureInvariantValues, ValidationCompareOperator.GreaterThan, ValidationDataType.Date) Then
                Throw New HttpException("MinimumDate property cannot be greater then MaximumValue")
            End If
        End If
 
        Return True
    End Function
 
    Protected Overloads Overrides Function EvaluateIsValid() As Boolean
        Dim day As Integer = -1
        Dim month As Integer = -1
        Dim year As Integer = -1
 
        Try
            If Not Integer.TryParse(MyBase.GetControlValidationValue(Me.DayToValidate), day) Then
                If Not (day >= 1 AndAlso day <= 31) Then
                    Return False
                End If
            End If
 
            If Not Integer.TryParse(MyBase.GetControlValidationValue(Me.MonthToValidate), month) Then
                If Not (month >= 1 AndAlso month <= 12) Then
                    Return False
                End If
            End If
 
            If Not Integer.TryParse(MyBase.GetControlValidationValue(Me.YearToValidate), year) Then
                If Not (year >= 1 AndAlso year <= 9999) Then
                    Return False
                End If
            End If
 
            If (Me.MinimumValue <> "" AndAlso Me.MaximumValue <> "") Then
                Dim val As Date = New Date(year, month, day)
                Dim min As Date = ConvertCultureInvariantToCurrentCultureDate(Me.MinimumValue)
                Dim max As Date = ConvertCultureInvariantToCurrentCultureDate(Me.MaximumValue)
 
                Return (val >= min AndAlso val <= max)
            Else
                Return True
            End If
        Catch ex As Exception
            Return False
        End Try
    End Function
 
    Protected Overloads Overrides Sub OnPreRender(ByVal e As EventArgs)
        MyBase.OnPreRender(e)
        If MyBase.RenderUplevel Then
            Me.Page.ClientScript.RegisterClientScriptResource(GetType(DateFieldsValidator), "DanielKatz.Web.UI.DateFieldsValidator.js")
        End If
    End Sub
 
#End Region
 
#Region " Helpers "
 
    Private Function ConvertCultureInvariantToCurrentCultureFormat(ByVal valueInString As String) As String
        Dim tmp As Object = Nothing
 
        BaseCompareValidator.Convert(valueInString, Type, True, tmp)
 
        If TypeOf tmp Is DateTime Then
            Dim time As DateTime = CDate(tmp)
            Return time.ToShortDateString
        Else
            Throw New HttpException("DateFieldsValidator supports only date value type")
        End If
 
    End Function
 
    Private Function ConvertCultureInvariantToCurrentCultureDate(ByVal valueInString As String) As DateTime
        Dim tmp As Object = Nothing
 
        BaseCompareValidator.Convert(valueInString, Type, True, tmp)
 
        If TypeOf tmp Is DateTime Then
            Dim time As DateTime = CDate(tmp)
            Return time
        Else
            Throw New HttpException("DateFieldsValidator supports only date value type")
        End If
 
    End Function
 
#End Region
 
#Region " Properties "
 
    <Category("Behavior"), Themeable(False), DefaultValue(""), IDReferenceProperty(), TypeConverter(GetType(ValidatedControlConverter)), Description("ID of the day field")> _
    Public Property DayToValidate() As String
        Get
            Return CType((If(ViewState("DayToValidate") Is Nothing, String.Empty, ViewState("DayToValidate"))), String)
        End Get
        Set(ByVal value As String)
            ViewState("DayToValidate") = value
        End Set
    End Property
 
    <Category("Behavior"), Themeable(False), DefaultValue(""), IDReferenceProperty(), TypeConverter(GetType(ValidatedControlConverter)), Description("ID of the month field")> _
    Public Property MonthToValidate() As String
        Get
            Return CType((If(ViewState("MonthToValidate") Is Nothing, String.Empty, ViewState("MonthToValidate"))), String)
        End Get
        Set(ByVal value As String)
            ViewState("MonthToValidate") = value
        End Set
    End Property
 
    <Category("Behavior"), Themeable(False), DefaultValue(""), IDReferenceProperty(), TypeConverter(GetType(ValidatedControlConverter)), Description("ID of the year field")> _
    Public Property YearToValidate() As String
        Get
            Return CType((If(ViewState("YearToValidate") Is Nothing, String.Empty, ViewState("YearToValidate"))), String)
        End Get
        Set(ByVal value As String)
            ViewState("YearToValidate") = value
        End Set
    End Property
 
    <Category("Behavior"), Themeable(False), DefaultValue(""), Description("Minimum date value, formatted as yyyy/MM/dd")> _
    Public Property MinimumValue() As String
        Get
            Return CType((If(ViewState("MinimumValue") Is Nothing, String.Empty, ViewState("MinimumValue"))), String)
        End Get
        Set(ByVal value As String)
            ViewState("MinimumValue") = value
        End Set
    End Property
 
    <Category("Behavior"), Themeable(False), DefaultValue(""), Description("Maximum date value, formatted as yyyy/MM/dd")> _
    Public Property MaximumValue() As String
        Get
            Return CType((If(ViewState("MaximumValue") Is Nothing, String.Empty, ViewState("MaximumValue"))), String)
        End Get
        Set(ByVal value As String)
            ViewState("MaximumValue") = value
        End Set
    End Property
 
#End Region
 
#Region " Unsupported Properties "
 
    <Browsable(False), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows Property ControlToValidate() As String
        Get
            Return String.Empty
        End Get
        Set(ByVal value As String)
            Throw New NotSupportedException("The property isn't supported. Use DayToValidate, MonthToValidate, YearToValidate properties instead.")
        End Set
    End Property
 
    <Browsable(False), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows Property SetFocusOnError() As Boolean
        Get
            Return False
        End Get
        Set(ByVal value As Boolean)
            Throw New NotSupportedException("SetFocusOnError is not supported.")
        End Set
    End Property
 
    <Browsable(False), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows Property Type() As ValidationDataType
        Get
            Return ValidationDataType.Date
        End Get
        Set(ByVal value As ValidationDataType)
            Throw New NotSupportedException("Type is not supported.")
        End Set
    End Property
 
#End Region
 
End Class

DateFieldsValidator.js

function DateFieldsValidatorEvaluateIsValid(val) 
{
    var day = parseInt(ValidatorTrim(ValidatorGetValue(val.dayControl)));
    var month = parseInt(ValidatorTrim(ValidatorGetValue(val.monthControl)));
    var year = parseInt(ValidatorTrim(ValidatorGetValue(val.yearControl)));
 
    if (!isNaN(day) && !isNaN(month) && !isNaN(year))
    {
        if ((day >= 1 && day <= 31) && (month >= 1 && month <= 12) && (year >= 1 && year <=9999))
        {
            if (val.minimumValue.length > 0 && val.maximumValue.length > 0)
            {
                var date = year + "/" + month + "/" + day;
 
                return (ValidatorCompare(date, val.minimumValue, "GreaterThanEqual", val) &&
                        ValidatorCompare(date, val.maximumValue, "LessThanEqual", val));
            }
            else
                return true;
        }
        else
            return false;
    }
    else
        return false;
}

AssemblyInfo.vb

Imports System.Web.UI
 
<Assembly: TagPrefix("DanielKatz.Web.UI", "dk")> 
<Assembly: WebResource("DanielKatz.Web.UI.DateFieldsValidator.js", "application/x-javascript")> 

Tags: ,

.NET

הוסף תגובה


(יציג את האייקון ה-Gravatar שלך)

  Country flag

biuquote
  • הערה
  • תצוגה מקדימה
Loading