For developers: Validate client binder forms
When working with forms in client binders, a simple, yet powerful validation feature is at your disposal. The validation is based on jQuery Validation plugin, which has been customized and streamlined for Sitefinity CMS Client binders.
Client binder validation supports following rules:
- required - Ensures that the value has been entered in the field.
- minlength - Ensures that the entered value has at least 'n' number of characters
- maxlength - Ensures that the entered value has at most 'n' number of characters
- rangelength - Ensures that the entered value has at least 'n' number of characters and at most 'm' number of characters.
- min - Ensures that the entered value is at least 'n'
- max - Ensures that the entered value is at most 'n'.
- range - Ensures that the entered value is between 'n' and 'm'
- email - Ensures that the entered value is a valid email address
- url - Ensures that the entered value is a valid URL
- date - Ensures that the entered value is a valid date
- dateISO - Ensures that the entered value is a valid ISO format date
- number - Ensures that the entered value is a number
- digits - Ensures that the entered value is composed only of digits
- accept - Ensures that the entered value ends with a given extension
- equalTo - Ensures that the entered value is same as the value of specified element
- regex - Ensures that the entered value matches the given regular expresssion
Marking fields for validation
With Sitefinity CMS client binders, marking fields for validation is extremely simple. All we have to do is add validation rules to the binder right after the binder has been initialized. Let us take a look at the following example:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Stores.aspx.cs" Inherits="Stores" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<%@ Register TagPrefix="sitefinity" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
<
head
runat
=
"server"
>
<
title
>Stores with Generic Collection client binder</
title
>
</
head
>
<
body
xmlns:sys
=
"javascript:Sys"
xmlns:dataview
=
"javascript:Sys.UI.DataView"
sys:activate
=
"*"
xmlns:code
=
"http://schemas.microsoft.com/aspnet/code"
>
<
form
id
=
"form1"
runat
=
"server"
>
<
asp:ScriptManager
ID
=
"scriptManager1"
runat
=
"server"
>
<
Scripts
>
<
asp:ScriptReference
Name
=
"MicrosoftAjax.js"
Path
=
"~/Sitefinity/Scripts/MicrosoftAjax.js"
/>
<
asp:ScriptReference
ScriptMode
=
"Inherit"
Path
=
"~/Sitefinity/Scripts/MicrosoftAjaxTemplates.js"
/>
<
asp:ScriptReference
ScriptMode
=
"Inherit"
Path
=
"~/Sitefinity/Scripts/MicrosoftAjaxAdoNet.js"
/>
</
Scripts
>
</
asp:ScriptManager
>
<
select
id
=
"storesDropDown"
runat
=
"server"
>
</
select
>
<
input
type
=
"button"
onclick
=
"OpenStore();"
value
=
"Open"
/>
<
input
type
=
"button"
onclick
=
"NewStore();"
value
=
"New store"
/>
<
sitefinity:GenericCollectionBinder
id
=
"storesBinder"
runat
=
"server"
TargetId
=
"storesDropDown"
ServiceUrl
=
"~/Sitefinity/Services/Commerce/Stores.svc"
BindOnLoad
=
"true"
DataKeyNames
=
"Id"
DataMembers
=
"Name, Id"
>
<
Containers
>
<
sitefinity:BinderContainer
ID
=
"BinderContainer1"
runat
=
"server"
RenderContainer
=
"false"
TemplateHolderTag
=
"SELECT"
>
<
option
value
=
"{{Id}}"
>{{Name}}</
option
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:GenericCollectionBinder
>
<
div
id
=
"storeForm"
runat
=
"server"
>
</
div
>
<
sitefinity:FormBinder
ID
=
"storeFormBinder"
runat
=
"server"
TargetId
=
"storeForm"
ServiceUrl
=
"~/Sitefinity/Services/Commerce/Stores.svc"
BindOnLoad
=
"false"
OnClientBinderInitialized
=
"StoresBinderInitialized"
OnClientSaved
=
"StoreSaved"
DataKeyNames
=
"Id"
DataMembers
=
"Id, Name, Description"
>
<
Containers
>
<
sitefinity:BinderContainer
ID
=
"BinderContainer2"
runat
=
"server"
>
<
fieldset
>
<
legend
>Store info:</
legend
>
<
ul
>
<
li
>
Store name:
<
br
/>
<
input
id
=
"Name"
name
=
"Name"
type
=
"text"
sys:value
=
"{{Name}}"
/>
</
li
>
<
li
>
Store description:
<
br
/>
<
input
id
=
"Description"
name
=
"Description"
type
=
"text"
sys:value
=
"{{Description}}"
/>
</
li
>
</
ul
>
<
input
type
=
"button"
sys:value
=
"Save changes"
onclick
=
"SaveChanges();"
/>
</
fieldset
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:FormBinder
>
<
script
type
=
"text/javascript"
>
function StoresBinderInitialized(sender, args) {
sender.AddValidationRule('Name', 'required', 'You must enter the store name!');
sender.AddValidationRule('Description', 'required', 'Description of the store is required');
}
function OpenStore() {
var storeId = $('#' + '<%= storesDropDown.ClientID %>').val();
var storeFormBinder = $find('<%= storeFormBinder.ClientID %>');
storeFormBinder.get_globalDataKeys()["Id"] = storeId;
storeFormBinder.DataBind();
}
function NewStore() {
var storeFormBinder = $find('<%= storeFormBinder.ClientID %>');
storeFormBinder.get_globalDataKeys()["Id"] = storeFormBinder.GetEmptyGuid();
storeFormBinder.DataBind();
}
function SaveChanges() {
var storeFormBinder = $find('<%= storeFormBinder.ClientID %>');
storeFormBinder.SaveChanges();
}
function StoreSaved() {
var storeFormBinder = $find('<%= storeFormBinder.ClientID %>');
storeFormBinder.ClearTarget();
var storesBinder = $find('<%= storesBinder.ClientID %>');
storesBinder.DataBind();
}
</
script
>
</
body
>
</
html
>
If you take a look at the declaration of storeFormBinder above, you will notice that we have subscribed to the OnClientBinderInitialized event and handled it in the function:
Binder setup: If you are developing inside of the Sitefinity CMS admin area, it is not necessary to declare ScriptManager control or add anything to the body element, since all this has been implemented on the base Sitefinity CMS admin page.
function StoresBinderInitialized(sender, args) {
sender.AddValidationRule('Name', 'required', 'You must enter the store name!');
sender.AddValidationRule('Description', 'required', 'Description of the store is required');
}
So, to add a new validation rule all we have to do is call the AddValidationRule method on the binder (in this case sender) and supply it with following arguments:
- Id of the element to validate
- Name of the validation rule
- Message to be displayed in case field does not validate [optional]
- Validation rule argument [optional]
If you do not specify the message, the default value in english will be displayed. Certain rules require you to pass the validation argument (for example, 'minlenght' will required you to pass the minimum number of characters as the validation rule argument.
When is form validated
Every time you call the SaveChanges method of the binder, form will be automatically validated and save operation will be carried only if the form passes the validation.
If you need to check if the form is valid, you can also call the IsValid function of the client binder which will validate the form and return 'true' if form is valid and 'false' otherwise.
var
storeFormBinder = $find(
'<%= storeFormBinder.ClientID %>'
);
var
formValid = storeFormBinder.IsValid();
Implementation samples
In this section we will provide a samples for implementing all supported validation rules. All samples will be made for the field with Id "TestField" declared as follows:
required
This rule makes sure that the field which is being validated is not empty; in other words, that a value has been entered:
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'required'
,
'You must enter the store name!'
);
}
Fails for: "" - Passes for "xyz"minlength
This rule makes sure that the field which is being validated has a value that has at least the specified number of characters:
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'minlength'
,
'You must specify at least {0} characters!'
, 4);
}
Fails for: "pit" - Passes for "apple"
maxlength
This rule makes sure that the field which is being validated has a value that has at most the specified number of characters.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'maxlength'
,
'You must specify at most {0} characters!'
, 5);
}
Argument placeholders: Note how you can specify the number placeholder in the message, which will be replaced with the value specified as the rule argument.
Fails for: "Mirror" - Passes for "pit"
rangelength
This rule makes sure that the field which is being validated has a value which length is between the two specified ends of the range.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'rangelength'
,
'You must enter between {0} and {1} characters!'
, [2,5]);
}
Argument placeholders: Note how you can specify the number placeholder in the message, which will be replaced with the value specified as the rule argument.
Fails for "a", Fails for "Mirror" - Passes for "apple"
min
This rule makes sure that the field which is being validated has a numeric value which is equal or larger than the specified value.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'min'
,
'You must enter number larger than {0}'
, 10);
}
Argument placeholders: Note how you can specify the number placeholders in the message, where the first placeholder is used for the start of the range and second placeholder is used for the end of the range.
Fails for: "4" - Passes for "10", Passes for "14"
max
This rule makes sure that the field which is being validated has a numeric value which is equal or smaller than the specified value.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'max'
,
'You must enter number smaller of equal to larger than {0}'
, 60);
}
Argument placeholders: Note how you can specify the number placeholder in the message, which will be replaced with the value specified as the rule argument.
Fails for: "61", "100" - Passes for "60", "12"
range
This rule makes sure that the field which is being validated has a value which is between the two specified ends of the range.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'range'
,
'You must enter number between {0} and {1}!'
, [10,20]);
}
Argument placeholders: Note how you can specify the number placeholder in the message, which will be replaced with the value specified as the rule argument.
Fails for: "1", "21", "100" - Passes for "10", "15", "20"
email
This rule makes sure that the field which is being validated has a value that is a valid email address:
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'email'
,
'You must enter a valid email address!'
);
}
Argument placeholders: Note how you can specify the number placeholders in the message, where the first placeholder is used for the start of the range and second placeholder is used for the end of the range.
Fails for: "test" - Passes for "test@test.com"
url
This rule makes sure that the field which is being validated has a value that is a valid URL.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'url'
,
'You must enter a valid URL.'
);
}
Fails for: "test", "www.test.com" - Passes for "http://www.test.com"
date
This rule makes sure that the field which is being validated has a value that is a valid date.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'date'
,
'You must enter a valid date.'
);
}
Fails for: "test", "30092009" - Passes for "30/09/2009"
dateISO
This rule makes sure that the field which is being validated has a value that is a valid ISO format date.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'dateISO'
,
'You must enter a valid ISO format date.'
);
}
Fails for: "test", "30/09/2009" - Passes for "2009-09-30"
number
This rule makes sure that the field which is being validated has a value that is a valid number.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'number'
,
'You must enter a valid number.'
);
}
Fails for: "test", "a34" - Passes for "12", "33.33", "12,541.33"
digits
This rule makes sure that the field which is being validated has a value that consists only of digits.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'digits'
,
'You must enter only digits.'
);
}
Fails for: "test", "a45", "33.12" - Passes for "1", "12846"
accept
This rule makes sure that the field which is being validated has a value (usually file name) which ends with a specified extension.
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'accept'
,
'You must select JPG or GIF image.'
,
"gif|jpg"
);
}
Fails for: "test", "test.pdf" - Passes for "test.jpg", "test.gif"
equalTo
This rule is used to ensure that two fields have the same value. For this example we will use two fields:
<input id=
"TestField"
name=
"TestField"
type=
"text"
/>
<input id=
"TestFieldX"
name=
"TestFieldX"
type=
"text"
/>
The ValidationRule will look like this:
function
StoresBinderInitialized(sender, args) {
sender.AddValidationRule(
'TestField'
,
'equalTo'
,
'TestField and TestFieldX must have same values'
,
"TestFieldX"
);
}
Validation will pass if both fields have the same value; otherwise it will fail.
regex
This rule is used to ensure that value entered into the field being validated matches the given regular expression:
sender.AddValidationRule(
'Name'
,
'regex'
,
'Name must contain only word characters.'
,
'^[\\w+]'
);
Fails for: "@#$", "@test", Passes for: "test", "mark"