Changing textbox border and background on validation fail - asp.net

is it possible to use javascript so that when an asp.net validator fails (for example the input doesnt match the regex), the textbox border and background color changes to a shade of red. Iv seen this before, but i forgot where.
Can someone please link me to a live example of such?
And a way i can do this?
Thanks
Edit:
Using this solution:
validateField = function(sender, args){
//do your validation logic
if (!args.IsValid){
var ctrl = $("#" + sender.controltovalidate);
if (ctrl){
ctrl.css({ "background-color" : "#990000", "border" : "1px solid #993300" });
}
}
return args.IsValid;
}
If i where to use regular exressions, is this the correct way to do it?
validateField = function(sender, args){
var regEx=(some regex forumla)
if (sender.value.search(regEx)==-1)
var ctrl = $("#" + sender.controltovalidate);
if (ctrl){
ctrl.css({ "background-color" : "#990000", "border" : "1px solid #993300" });
}
}
else
{
return args.IsValid;
}
}
Sorry for my lack of knowledge, iv never used javascript before. Also, what is the:
return args.IsValid;
At the end for?

You can use a CustomValidator, and if validation fails you can change the border and background colors in the client-side validation function:
Validation function:
validateField = function(sender, args){
//do your validation logic
if (!args.IsValid){
var ctrl = $("#" + sender.controltovalidate);
if (ctrl){
ctrl.css({ "background-color" : "#990000", "border" : "1px solid #993300" });
}
}
return args.IsValid;
}
Markup:
<asp:TextBox ID="TextBox1" runat="server" />
<asp:CustomValidator ID="CustomValidator1" runat="server" EnableClientScript="true"
ErrorMessage="Required"
ClientValidationFunction="validateField"
ControlToValidate="TextBox1"
Display="Dynamic">
</asp:CustomValidator>

I have done something like this
Private Sub HighlightInvalidFields()
For Each validator As IValidator In Page.Validators
If TypeOf validator Is BaseValidator Then
If CType(validator, BaseValidator).IsValid = False Then
Dim controlId As String = CType(validator, BaseValidator).ControlToValidate
Dim control As WebControl = TryCast(Me.FindControlRecursive(controlId), WebControl)
If control IsNot Nothing Then
control.Style.Add("background-color", "#B85449")
End If
End If
End If
Next
End Sub
I call it from the page_prerender
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
If Page.IsPostBack Then HighlightInvalidFields()
End Sub

public class ChangeColorPage : Page {
public Label lblZip;
public RegularExpressionValidator valZip;
protected override void OnLoad(EventArgs e) {
Page.Validate();
lblZip.ForeColor = valZip.IsValid? Color.Black : Color.Red;
}
}
<asp:Label id=lblZip runat=server Text="Zip Code:"/>
<asp:TextBox id=txtZip runat=server OnChange="txtZipOnChange();" /></asp:TextBox><br>
<asp:RegularExpressionValidator id=valZip runat=server ControlToValidate=txtZip ErrorMessage="Invalid Zip Code" ValidationExpression="[0-9]{5}" /><br>
<script language=javascript>
function txtZipOnChange() {
// Do nothing if client validation is not active
if (typeof(Page_Validators) == "undefined") return;
// Change the color of the label
lblZip.style.color = valZip.isvalid ? "Black" : "Red";
}
</script>
http://msdn.microsoft.com/en-us/library/aa479045.aspx

Related

Show red border on textbox on error

I am trying to show an error by changing the color of the border of a text box. I have found a lot of posts on how to do it, but I have never done anything with 'Validators' so I am confused where to start, or where to put the code.
Similar posts:
Post One
Post Two
My main question(s) are, where do I put the JS code? And secondly, how do I call the code?
Current Code
If TicketNumber.Text = String.Empty = True Then
NotificationLabel.Text = "Ticket Number must be filled out"
Exit Sub
End If
A RequiredFieldValidator could do it with some tricks explained here, and here. Another way is to use a CustomValidator like the following.
aspx mark-up
<asp:TextBox runat="server" ID="tbText" />
<asp:CustomValidator ID="cvCustom" ErrorMessage="Ticket Number must be filled out"
ControlToValidate="tbText" runat="server" OnServerValidate="ValidateInput"
ClientValidationFunction="ValidateInput" ValidateEmptyText="True" />
<asp:Button Text="My Button" runat="server" />
Javascript
<script type="text/javascript">
function ValidateInput(sender, args) {
if (args.Value == '') {
args.IsValid = false;
document.getElementById('<%= tbText.ClientID %>').style.borderColor = "red";
return false;
}
return true;
}
</script>
Code Behind (C#)
protected void ValidateInput(object source, ServerValidateEventArgs args)
{
if(string.IsNullOrWhiteSpace(args.Value))
{
args.IsValid = false;
tbText.Style["border-color"] = "red";
}
else
{
args.IsValid = true;
}
}

How do I highlight a textbox border red when it is required?

What property do I use on the required field validator control to make the textbox red if there is a validation error?
Here is my code:
<asp:Label ID="lblFirstName" runat="server" AssociatedControlID="txtFirstName" Text="First Name:" CssClass="reg-labels" />
<br />
<asp:TextBox ID="txtFirstName" runat="server" CausesValidation="true" MaxLength="60" CssClass="standard_width"/>
<asp:RequiredFieldValidator ControlToValidate="txtFirstName" runat="server" ID="valFirstName" ValidationGroup="grpRegistration" ErrorMessage="First Name is required." Text="*" />
ASP.Net web forms internally uses a Javascript frameworka located at aspnet_client\{0}\{1} folder to handle the validation, etc. They are basically determined from the property ClientScriptsLocation
Try overriding the default framework function by keeping it in your page includes additional line to set the control_to_validate color
document.getElmentById(val.controltovalidate).style.border='1px solid red';
<asp:TextBox ID="txtFirstName" runat="server" CausesValidation="true" MaxLength="60"
CssClass="standard_width" />
<asp:RequiredFieldValidator ControlToValidate="txtFirstName" runat="server" ID="valFirstName" ValidationGroup="grpRegistration" ErrorMessage="First Name is required." Text="*" />
<asp:Button Text="Super" ID="btnSubmit" CausesValidation="true" runat="server" />
JS
<script type="text/javascript">
function ValidatorUpdateDisplay(val) {
if (typeof (val.display) == "string") {
if (val.display == "None") {
return;
}
if (val.display == "Dynamic") {
val.style.display = val.isvalid ? "none" : "inline";
return;
}
}
val.style.visibility = val.isvalid ? "hidden" : "visible";
if (val.isvalid) {
document.getElementById(val.controltovalidate).style.border = '1px solid #333';
}
else {
document.getElementById(val.controltovalidate).style.border = '1px solid red';
}
}
</script>
Without overloading anything, give your <asp:*Validator tags a CssClass="garbage" attribute.
In your style sheet, create
.garbage {
display: none;
}
.garbage[style*=visible] + input,
.garbage[style*=visible] + select,
.garbage[style*=visible] + textarea {
background-color: #ffcccc;
border: 1px solid #ff0000;
}
and any form control immediately preceded by a validator will be highlighted on invalid data.
EDIT:
I've seen a few methods for forcing a redraw in Chrome, including a pure css solution: transform: translateZ(0);
Murali's answer works great, but I rolled a jQuery version for myself if anyone's interested.
Based on the official documentation (https://msdn.microsoft.com/en-us/library/yb52a4x0.aspx), I was able to get each validator and check to see if it isvalid, and if not, use the errormessage property to populate my own notification system (setStatusMessage() is a function I wrote, feel free to use any other type of status message prompt, like alert() or roll your own).
/*
* Validation Catcher - Sean D Kendle - 9/24/2015
* Catch validation events and add to status messages system
*/
$(document).on("submit", function () {
$.each(Page_Validators, function (i, v) {
var strControlToValidateID = v.controltovalidate;
var $controlToValidate = $("#" + strControlToValidateID);
var arrInvalidControls = new Array(); //collection of all invalid field ids for later
if (!v.isvalid) {
$controlToValidate.addClass("error"); //custom error class, optional
$controlToValidate.css("border-color", "#D00"); //manually set border-color per OP's question
$(".error").eq(0).focus(); /*set focus to top-most invalid field on error, or you can use the v.focusOnError property to check if validator has this set (string "t" if true), but I don't want to have to set this every time*/
arrInvalidControls.push(strControlToValidateID); //collect all invalid field ids for later
$(v).addClass("redtext"); //custom class - allows me to make all errors red without having to add a ForeColor property to every validator
setStatusMessage(v.errormessage, "red", -1); // setStatusMessage is a function I wrote, replace with another alert system if desired, or delete this line
} else {
/*the following prevents control being seen as valid if there are two or more validators for the control - example: required field validator, then custom or regex validator (first would be invalid, second would be valid for empty field)*/
if (!$.inArray(strControlToValidateID, arrInvalidControls)) {
$controlToValidate.removeClass("error");
$controlToValidate.css("border-color", "");
} else {
//console.log(strControlToValidateID + " is already invalid.");
}
}
});
});
I hope this helps someone!
Well, to your disappointment there isn't a direct way (cf https://stackoverflow.com/a/5249021/145682)
However, you can make use of a CustomValidator. Here is one way to define it:
<asp:TextBox ID="txtbx" runat="server"></asp:TextBox>
<asp:CustomValidator ID="customValidator"
runat="server" ValidationGroup="submit" ControlToValidate="txtbx"
ClientValidationFunction="foo" ErrorMessage="*"></asp:CustomValidator>
Make note of the ClientValidationFunction. It has to be written as follows:
function foo(sender, e) {
var value = e.Value;
console.log('Value: ', e.Value);
var ctrlid = sender.controltovalidate;
var targetControl = document.getElementById(ctrlid);
if (vowels.indexOf(value[0].toLowerCase()) == -1) {
console.log('true-executed');
e.isValid = false;
targetControl.style.borderColor = 'red';
}
else {
console.log('else-executed');
e.isValid = true;
targetControl.style.borderColor = '';
}
}
The controltovalidate property of sender will give you the id of the control you are looking for; in other words, your ControlToValidate. And, Value property of e should give you the target control's value.
The other option, is you can write your own server control to do the job: http://msdn.microsoft.com/en-us/library/aa719624(v=vs.71).aspx
Murali's answer worked for me as data changes, but on postback all the fields rendered as though there were no validation errors. I found that ASP.NET lazy-loads ValidatorUpdateDisplay, so the client-side override doesn't take effect until after it's already passed its onload validation. I'm guessing there's either a version or an implementation difference that blocked me here, but other solutions (including a few with CSS) weren't working either.
Eventually, I came upon a solution that combines Murali's answer with Dillie-O's solution from here: Change Text Box Color using Required Field Validator. No Extender Controls Please
<div class="pad-left">
<asp:CompareValidator ID="comvIncTaxable" runat="server" ControlToValidate="tbIncTaxable" Display="Dynamic" Operator="DataTypeCheck" Type="Currency" CssClass="red-border"
ErrorMessage="Please enter a currency value.">
<span></span>
</asp:CompareValidator>
<asp:TextBox runat="server" ID="tbIncTaxable"></asp:TextBox>
</div>
<script type="text/javascript">
$(function () {
setValidatedBordersOnLoad();
});
function ValidatorUpdateDisplay(val) {
if (typeof (val.display) == "string") {
if (val.display == "None") {
return;
}
if (val.display == "Dynamic") {
val.style.display = val.isvalid ? "none" : "inline";
if (val.className == 'red-border' && val.controltovalidate) {
if (val.isvalid) {
document.getElementById(val.controltovalidate).style.border = '1px solid #ccc';
}
else {
document.getElementById(val.controltovalidate).style.border = '1px solid red';
}
}
return;
}
}
val.style.visibility = val.isvalid ? "hidden" : "visible";
}
function setValidatedBordersOnLoad()
{
for (var i = 0; i < Page_Validators.length; i++)
{
var val = Page_Validators[i];
if (val.className == 'red-border' && val.controltovalidate) {
var ctrl = document.getElementById(val.controltovalidate);
if (ctrl != null && ctrl.style != null) {
if (!val.isvalid)
ctrl.style.border = '1px solid red';
else
ctrl.style.border = '1px solid #ccc';
}
}
}
}
</script>
The nice thing about this solution is it lets you cherry-pick which validators get this special handling simply by adding CssClass='red-border' to the validator. In my case, I only wanted this behavior on fields within a specific grid where cell positioning shouldn't change, but still wanted to use out-of-box functionality elsewhere on the form.

How to get Text value of UserControl in Repeater Control itemCommand in asp.net?

I have developed usercontrol timePicker. I'm using Bootstrap and Ajaxtoolkit 4 but not using updatepanel
<%# Control Language="C#" AutoEventWireup="true" CodeFile="TimePicker.ascx.cs" Inherits="Controls_TimePicker" %>
<script type="text/javascript">
$(function () {
$('#<%=divTime.ClientID %>').datetimepicker({
/* language: 'ar-kw',*/
language: 'en-US',
maskInput: true,
format: 'HH:mm PP',
pickDate: false,
pickSeconds: false,
pick12HourFormat: true,
pickTime: true,
placement: 'left'
});
});
</script>
<div id="divTime" clientidmode="AutoID" runat="server" class="input-append date dropup">
<span class="add-on "><i data-time-icon="icon-time" data-date-icon="icon-calendar"></i>
</span>
<asp:TextBox ID="txtDate" ClientIDMode="Predictable" Width="65%" type="text" runat="server"></asp:TextBox>
</div>
C#:
public string Text
{
get { return txtDate.Text; }
set { txtDate.Text = value; }
}
By this property I can get Text Value from my webpage. It's working fine, but now I want to use Usercontrol (Timepicker) in repeater. Here is the code:
protected void repeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
UserControl tmStart = (UserControl)e.Item.FindControl("tmStart");
Label lblStartTime = (Label)e.Item.FindControl("lblStartTime");
tmStart.Text = lblStart.Text;
}
It's working fine outside repeater but in repeater it's not working, tmStart.Text (Text is giving error). Any idea what's wrong?
You should cast the tmStart control as the specific control, not the generic UserControl. The you will have access to the the Text Property.
protected void repeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
Controls_TimePicker tmStart = (Controls_TimePicker)e.Item.FindControl("tmStart");
Label lblStartTime = (Label)e.Item.FindControl("lblStartTime");
tmStart.Text = lblStart.Text;
}
I have solved this by using rightclick on the variable and click quick info
this worked for me
((Controls_TimePicker)(tmStartEdit)).Text = lblStartTime.Text;
((Controls_TimePicker)tmEndEdit).Text = lblEndTime.Text;
((Controls_DatePickerAdmin)(cldrStartEdit)).Text = lblStartDate.Text;
((Controls_DatePickerAdmin)(cldrEndEdit)).Text = lblEndDate.Text;
//Controls_TimePicker is showing red but runtime is not giving error dont know why.

CustomValidator using CustomValidationScript

I have an ASP.NET TextBox with a CustomValidation control that invokes client side validation script.
<asp:TextBox ID="txtSubsContrRbtAmt" runat="server"
CssClass="textEntry NumericInput" Width="150px"
Text="" onKeyUp="SumValues();" MaxLength="16"></asp:TextBox>
<asp:CustomValidator ID="cvalSubsContrRbtAmt" runat="server" ClientValidationFunction="ValidatetxtSubsContrRbtAmt"
ControlToValidate="txtSubsContrRbtAmt" CssClass="errlable" ErrorMessage="Max Decimals = 7"
SetFocusOnError="True" ValidationGroup="CarbsAdd"></asp:CustomValidator>
Here's the Client script:
function ValidatetxtSubsContrRbtAmt(source, args) {
var txtSubsContrRbtAmt = document.getElementById("<%=txtSubsContrRbtAmt.ClientID%>");
var amount = txtSubsContrRbtAmt.value;
args.IsValid = ValidAmount(amount);
if (!args.IsValid)
txtSubsContrRbtAmt.focus();
}
function ValidAmount(amount) {
if (isNumber(amount)) {
return (RoundToXDecimalPlaces(amount, 7) == amount);
}
else {
return true;
}
In the ValidatetxtSubsContrRbtAmt function, the "source" parameter is the CustomValidator. That control has a property "ControlToValidate." If I can get to it, I can programmatically retrieve the value from that control and not have to have a separate function to validate each textbox.
jQuery is too much for me at this point, I'm looking for a plain old Javascript approach, please.
You don't have to get the text box. You can get the value from args.Value. The focus should be set automatically if you set SetFocusOnError="true".
function ValidatetxtSubsContrRbtAmt(source, args) {
var amount = args.Value;
args.IsValid = ValidAmount(amount);
}
You should be able to get to the control from the source object.
function ValidatetxtSubsContrRbtAmt(source, args) {
var controlToFocusOn = source.ControlToValidate;
you can switch that out with "document.getElementByID()" to get the ID or whatever attribute you need
var controlId = document.getElementById(source.ControlToValidate).id;
}
now you can focus or do what you need with the control. I had to access the the actual ControlToValidate earlier today from a CustomValidator.

Problem with ControlToValidate in dynamic create validation controls

Hi
I have site with two text boxes and dynamically create validation control. This is code from .aspx file:
<form runat="server">
<asp:TextBox AutoPostBack="true" ID="TextBox1" Text="" runat="server" Width="200px"
OnTextChanged="TextBox1_TextChanged"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server" Visible="True" Width="200px"AutoPostBack="true"></asp:TextBox>
<asp:Panel ID="Panel1" runat="server">
</asp:Panel>
<asp:TextBox ID="ValidationTB" runat="server" Visible="true"></asp:TextBox>
</form>
This is my code-behind:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (TextBox2.Visible)
{
if (!String.IsNullOrEmpty(TextBox1.Text) && String.IsNullOrEmpty(TextBox2.Text))
{
RequiredFieldValidator RequiredFieldValidator1 = new RequiredFieldValidator();
RequiredFieldValidator1.Enabled = true;
RequiredFieldValidator1.ErrorMessage = "Second field required";
RequiredFieldValidator1.Display = ValidatorDisplay.Dynamic;
RequiredFieldValidator1.ControlToValidate = "TextBox2";
Panel1.Controls.Add(RequiredFieldValidator1);
RequiredFieldValidator1.Validate();
}
if (!String.IsNullOrEmpty(TextBox2.Text) && String.IsNullOrEmpty(TextBox1.Text))
{
RequiredFieldValidator RequiredFieldValidator1 = new RequiredFieldValidator();
RequiredFieldValidator1.Enabled = true;
RequiredFieldValidator1.ErrorMessage = "First field required";
RequiredFieldValidator1.Display = ValidatorDisplay.Dynamic;
RequiredFieldValidator1.ControlToValidate = "TextBox1";
Panel1.Controls.Add(RequiredFieldValidator1);
RequiredFieldValidator1.Validate();
}
if (!String.IsNullOrEmpty(TextBox2.Text) && !String.IsNullOrEmpty(TextBox1.Text))
{
if (Convert.ToDateTime(TextBox2.Text) < Convert.ToDateTime(TextBox1.Text))
{
ValidationTB.Text = null;
RequiredFieldValidator RequiredFieldValidator1 = new RequiredFieldValidator();
RequiredFieldValidator1.Enabled = true;
RequiredFieldValidator1.ErrorMessage = "Bad range of dates";
RequiredFieldValidator1.Display = ValidatorDisplay.Dynamic;
RequiredFieldValidator1.ControlToValidate = "ValidationTB";
Panel1.Controls.Add(RequiredFieldValidator1);
RequiredFieldValidator1.Validate();
}
}
}
}
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
RegularExpressionValidator RegularExpressionValidator1 = new RegularExpressionValidator();
RegularExpressionValidator1.ValidationExpression = #"^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))$";
RegularExpressionValidator1.Enabled = true;
RegularExpressionValidator1.ErrorMessage = "Bad format of date";
RegularExpressionValidator1.Display = ValidatorDisplay.Dynamic;
if (!String.IsNullOrEmpty(TextBox1.Text))
{
RegularExpressionValidator1.ControlToValidate = "TextBox1";
Panel1.Controls.Add(RegularExpressionValidator1);
RegularExpressionValidator1.Validate();
}
if (!String.IsNullOrEmpty(TextBox2.Text))
{
RegularExpressionValidator1.ControlToValidate = "TextBox2";
Panel1.Controls.Add(RegularExpressionValidator1);
RegularExpressionValidator1.Validate();
}
}
}
TextBox ValidationTB is just to make validate on empty control.
This validation doesn't work, when I try:
1. To first textbox enter for example: 2009-09-09
2. To second textbox enter for example: 2009-10-09
Now, everything is OK.
3. I change my first textbox on for example 2009-12-09
I get error Bad range of dates - it's OK.
4. I correct first textbox on 2009-09-09, message disappear-OK.
5. Again enter to first textbox 2009-12-09 - I don't have error, but it should be.
What strange - in debug mode I can see, that in code:
if (Convert.ToDateTime(TextBox2.Text) < Convert.ToDateTime(TextBox1.Text))
{
ValidationTB.Text = null;
RequiredFieldValidator RequiredFieldValidator1 = new RequiredFieldValidator();
RequiredFieldValidator1.Enabled = true;
RequiredFieldValidator1.ErrorMessage = "Bad range of dates";
RequiredFieldValidator1.Display = ValidatorDisplay.Dynamic;
RequiredFieldValidator1.ControlToValidate = "ValidationTB";
Panel1.Controls.Add(RequiredFieldValidator1);
//In debug window: RequiredFieldValidator1.ControlToValidate = "TextBox2"
RequiredFieldValidator1.Validate();
}
instead of ValidationTB control, RequiredFieldValidator1.ControlToValidate is set to TextBox2 (it isn't empty, so I haven't error message).
Why TextBox2 is set to RequiredFieldValidator1.ControlToValidate instead of ValidationTB textbox and how I could solve this?
Thanks
Regards
It looks like what you are really wanting is a CompareValidator instead of what you are using.
Rewrite your 3rd IF block so that it looks like this:
if (!String.IsNullOrEmpty(TextBox2.Text) && !String.IsNullOrEmpty(TextBox1.Text))
{
Response.Write("Executing Block 3");
ValidationTB.Text = null;
CompareValidator CompareValidator1 = new CompareValidator();
CompareValidator1.Enabled = true;
CompareValidator1.ErrorMessage = "Bad range of dates";
CompareValidator1.Display = ValidatorDisplay.Dynamic;
CompareValidator1.Operator = ValidationCompareOperator.LessThan;
CompareValidator1.Type = ValidationDataType.Date;
CompareValidator1.ControlToCompare = TextBox2.ID;
CompareValidator1.ControlToValidate = TextBox1.ID;
Panel1.Controls.Add(CompareValidator1);
CompareValidator1.Validate();
}
This should give you the desired result.
Now... lets talk about some other things going on here.
First, unless you are just doing this as a proof of concept, then I highly encourage you to use the validators in a standard way. Nothing you are doing here requires that you add these validators in dynamically. Everything you want to accomplish can be achieved by simply adding the validators in the markup.
Second, your Event Handler for the text changed event is probably not going to do what you want. As it stands right now, it will fire too late in the page lifecycle to catch errors before your Page_Load event. Your current code will throw an exception if I enter "Blah" into both of the text boxes because it will attempt to convert those to DateTime types.
Lastly, when assigning ID's of existing controls you should use the ID property of that control instead of the Magic Strings you are using now. In this way you won't have to worry about changing the ID in multiple places if you decide to change it in markup.
Anyway, I hope this helps.
Shot in the dark, but try giving your validator controls IDs. RequiredFieldValidator1.ID = "HelloMyNameIsValidator1";

Resources