CompareValidator for DateTime
אפשר להוריד את דוגמת הקוד
מכאן:
נניח שיש לכם שני תיבות טקסט שהערכים שלהם הם תאריכים ואתם רוצים לוודא שאחד גדול מהשני (לדוגמא: From ו - To) - הערכים לתיבות הטקסט יכולים להגיע מכל מקור - או מהאובייקט Calendar של asp או מהאובייקט Calendar של ajax או מהאובייקט של טלריק - זה לא ממש משנה - הנקודה היא שאנחנו רוצים לבדוק שני תאריכים.
במחשבה ראשונה נשתמש ב - CompareValidator המובנה וזה יראה כך:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" ValidationGroup="dates" />
<asp:CompareValidator ID="CompareValidator1" runat="server" ErrorMessage="CompareValidator"
ControlToCompare="TextBox2" ControlToValidate="TextBox1" Operator="GreaterThan"
Type="Date" ValidationGroup="dates"></asp:CompareValidator>
ל - CompareValidator יש מאפיין בשם Type שאחד מהערכים שאפשר להכניס הוא Date ואז לכאורה המערכת אמורה לבדוק שהתאריך בתיבת הטקסט הראשונה גדול מהתאריך בתיבת הטקסט השנייה.
וזה אמנם עובד, אבל רק בתנאי שהתאריכים הם רק תאריכים ה - validator לא יודע לבדוק שעות או תאריכים שיש בהם שעות - קצת מטופש לדעתי שהם לא השקיעו עוד שעת פיתוח כדי להוסיף בדיקה גם על שעות.
אחרי דיבוג של הסקריפטים של מייקרוסופט (זה שווה פוסט נפרד איך עושים את זה) וחיפוש קצר בגוגל מצאתי
מישהו שנתן סוג של פיתרון - הוא משתמש שם ב - CustomValidator ובודק בעצמו, הרעיון די נחמד אבל העדפתי לשכלל אותו ולהשתמש ב - CompareValidator.
למעשה כדי לתקן את ההתנהגות של ה - CompareValidator אנחנו צריכים לחשוב גם על צד הלקוח (כלומר לשנות את ההתנהגות של הסקריפטים שרצים אצל הלקוח) וגם על צד השרת (כלומר לשנות את הבדיקה בצד השרת).
צד הלקוח:
מה שאנחנו נעשה כאן יהיה לשנות את המימוש של הפונקציה שבודקת את התאריכים.
צד השרת:
נוכל לבחור לרשת מה - CustomValidator או לדרוס את המתודה Validate ולעשות את הבדיקה לבד - (אני אדגים את שניהם).
מימוש:
צד הלקוח:
נוסיף ל - Validator מאפיין שנקרא לו IsDateTime (ב - html הרי מותר להוסיף כל מאפיין לכל תג)
<asp:CompareValidator ID="CompareValidator1" runat="server" ErrorMessage="CompareValidator"
ControlToCompare="TextBox2" ControlToValidate="TextBox1" Operator="GreaterThan" IsDateTime="true"
Type="Date" ValidationGroup="dates"></asp:CompareValidator>
במידה ונחליט בצד השרת לרשת מה - Validator מן הסתם נגדיר את המאפיין הזה. ואז זה יראה כך:
<cc1:DateTimeValidator ID="CompareValidator1" runat="server" ErrorMessage="CompareValidator"
ControlToCompare="TextBox2" ControlToValidate="TextBox1" Operator="GreaterThan"
IsDateTime="true" Type="Date" ValidationGroup="dates"></cc1:DateTimeValidator>
כשכמובן נוסיף בראש הדף את הרישום ל Control
<%@ Register Assembly="[Assembly]" Namespace="[Namesapce]" TagPrefix="cc1" %>
כעת נוסיף את הסקריפט הבא: (הסברים למטה)
<script type="text/javascript">
var OriginalValidatorCompare;
function ChangeValidatorCompare() {
if (typeof (ValidatorCompare) == "function") {
OriginalValidatorCompare = ValidatorCompare;
ValidatorCompare = function(operand1, operand2, operator, val) {
if (val.IsDateTime == undefined || val.IsDateTime.toLowerCase() != "true") {
return OriginalValidatorCompare(operand1, operand2, operator, val);
}
var result = OriginalValidatorCompare(operand1.substr(0, operand1.indexOf(' ', 0)),
operand2.substr(0, operand2.indexOf(' ', 0)),
operator, val);
if (result == false) {
return result;
}
var op1, op2;
var hour1 = operand1.substring(11, 13);
var minuts1 = operand1.substring(14, 16);
var secound1 = operand1.substring(17, 19);
var hour2 = operand2.substring(11, 13);
var minuts2 = operand2.substring(14, 16);
var secound2 = operand2.substring(17, 19);
op1 = new Date(0, 0, 0, hour1, minuts1, secound1);
op2 = new Date(0, 0, 0, hour2, minuts2, secound2);
switch (operator) {
case "NotEqual":
return (op1 != op2);
case "GreaterThan":
return (op1 > op2);
case "GreaterThanEqual":
return (op1 >= op2);
case "LessThan":
return (op1 < op2);
case "LessThanEqual":
return (op1 <= op2);
default:
return (op1 == op2);
}
}
}
}
</script>
ב - onload של הדף נפעיל את הפונקצייה ChangeValidatorCompare
מה שאנחנו עושים בפונקציה - זה למעשה לשנות את המימוש של הפונקציה המקורית.
יש לנו משתנה בשם OriginalValidatorCompare שאמור לשמור לנו מצביע לפונקציה המקורית.
כשמפעילים את ChangeValidatorCompare (בזמן טעינת הדף) אנחנו בודקים האם יש פונקציה בשם ValidatorCompare, במידה וכן אנחנו שומרים מצביע לפונקציה ומגדירים שמעכשיו קריאה ל - ValidatorCompare תפעיל פונקציה חדשה.
ברגע שמישהו ילחץ על הלחצן יופעלו הסקריפטים שאמורים לבדוק.
בתוך הסקריפט של מיקרוסופט יש קריאה לפונקציה ValidatorCompare - וכאמור זה יפעיל את הפונקציה שלנו.
בהתחלה אנחנו בודקים האם יש הגדרה ב - validator של IsDateTime והאם הוא מוגדר כ - true
במידה ולא נחזיר את התוצאה של הפונקציה המקורית.
במידה וכן - אנחנו נפעיל את קטע הקוד הבא:
var result = OriginalValidatorCompare(operand1.substr(0, operand1.indexOf(' ', 0)),
operand2.substr(0, operand2.indexOf(' ', 0)),
operator, val);
קוראים לפונקציה המקורית - אבל שולחים רק את התאריך (על ידי חיפוש במחרוזת שקבלנו את תו הרווח הראשון).
במידה וחזר false כמובן שנחזיר false מכיון שאין טעם לבדוק את השעות אם התאריכם לא עמדו בבדיקה.
במידה וחזר true - נבדוק את השעות
var hour1 = operand1.substring(11, 13);
var minuts1 = operand1.substring(14, 16);
var secound1 = operand1.substring(17, 19);
var hour2 = operand2.substring(11, 13);
var minuts2 = operand2.substring(14, 16);
var secound2 = operand2.substring(17, 19);
op1 = new Date(0, 0, 0, hour1, minuts1, secound1);
op2 = new Date(0, 0, 0, hour2, minuts2, secound2);
נוציא את השעות דקות ושניות מהתאריכים שקבלנו - ונייצר שני אובייקטים מסוג Date.
כעת נשאר רק לעשות את הבדיקה
switch (operator) {
case "NotEqual":
return (op1 != op2);
case "GreaterThan":
return (op1 > op2);
case "GreaterThanEqual":
return (op1 >= op2);
case "LessThan":
return (op1 < op2);
case "LessThanEqual":
return (op1 <= op2);
default:
return (op1 == op2);
}
זה למעשה מסכם לנו את צד הלקוח.
מימוש צד השרת:
public class DateTimeValidator : CompareValidator
{
public bool IsDateTime { get; set; }
protected override bool EvaluateIsValid()
{
if (!IsDateTime)
{
return base.EvaluateIsValid();
}
DateTime op1 = DateTime.Parse(((TextBox)FindControl(ControlToValidate)).Text);
DateTime op2 = DateTime.Parse(((TextBox)FindControl(ControlToCompare)).Text);
switch (Operator)
{
case ValidationCompareOperator.Equal:
return op1 == op2;
case ValidationCompareOperator.GreaterThan:
return op1 > op2;
case ValidationCompareOperator.GreaterThanEqual:
return op1 >= op2;
case ValidationCompareOperator.LessThan:
return op1 < op2;
case ValidationCompareOperator.LessThanEqual:
return op1 <= op2;
case ValidationCompareOperator.NotEqual:
return op1 != op2;
default:
return op1 == op2;
}
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
writer.AddAttribute("IsDateTime", IsDateTime.ToString());
base.AddAttributesToRender(writer);
}
}
ההסבר הוא כמובן מאוד פשוט:
הוספנו מאפיין בשם IsDateTime במתודה AddAttributeToRender דאגנו להסיף אותה ל - html
ובמתודה EvaluateIsValid מימשנו את הבדיקה.
במידה והיינו מחליטים לא לרשת מ - CompareValidator היינו צריכים לדרוס את המתודה Validate של הדף ולמצוא את ה - validator המתאים בתוך המאפיין Validators של הדף (שמכיל את כל ה - validators) ולהחליט האם המאפיין IsValid של ה - validator הוא true או false בהתאם לבדיקה שעשינו.