@using DevExtreme.MVC.Demos.ViewModels
@using(Html.BeginForm()) {
using(Html.DevExtreme().ValidationGroup()) {
@Html.AntiForgeryToken()
@(Html.DevExtreme().Form<EditorsViewModel>()
.OnInitialized("onInitialized")
.ShowValidationSummary(true)
.Items(items => {
items.AddGroup()
.Caption("Credentials")
.Items(groupItems => {
groupItems.AddSimpleFor(m => m.Email);
groupItems.AddSimpleFor(m => m.Password)
.Editor(e => e.TextBox()
.Mode(TextBoxMode.Password)
.OnValueChanged("passwordChanged")
.Buttons(buttons =>
{
buttons.Add()
.Name("password")
.Location(TextEditorButtonLocation.After)
.Widget(w => w.Button()
.Type(ButtonType.Default)
.Icon(Url.Content("~/Content/Images/icons/eye.png"))
.OnClick("() => changePasswordMode('Password')"));
})
);
groupItems.AddSimpleFor(m => m.ConfirmPassword)
.Editor(e => e.TextBox()
.Mode(TextBoxMode.Password)
.Buttons(buttons =>
{
buttons.Add()
.Name("password")
.Location(TextEditorButtonLocation.After)
.Widget(w => w.Button()
.Type(ButtonType.Default)
.Icon(Url.Content("~/Content/Images/icons/eye.png"))
.OnClick("() => changePasswordMode('ConfirmPassword')"));
})
);
});
items.AddGroup()
.Caption("Personal Data")
.Items(groupItems => {
groupItems.AddSimpleFor(m => m.Name);
groupItems.AddSimpleFor(m => m.Date);
});
items.AddGroup()
.Caption("Billing address")
.Items(groupItems => {
groupItems.AddSimpleFor(m => m.Country)
.Editor(e => e
.SelectBox()
.DataSource(d => d.WebApi().RouteName("GeoNames").LoadAction("Countries"))
);
groupItems.AddSimpleFor(m => m.City)
.Editor(e => e
.Autocomplete()
.MinSearchLength(2)
.DataSource(d => d.WebApi().RouteName("GeoNames").LoadAction("Cities"))
);
groupItems.AddSimpleFor(m => m.Address);
groupItems.AddSimpleFor(m => m.Phone)
.HelpText("Enter the phone number in USA phone format")
.Editor(e => e.TextBox()
.Mask("+1 (X00) 000-0000")
.MaskRules(new { X = new JS("/[02-9]/") })
.MaskInvalidMessage("The phone must have a correct USA phone format")
);
groupItems.AddSimpleFor(m => m.Accepted)
.Label(l => l.Visible(false))
.Editor(editor => editor.CheckBox().Text("I agree to the Terms and Conditions"));
});
items.AddButton()
.HorizontalAlignment(HorizontalAlignment.Left)
.ButtonOptions(b => b.Text("Register")
.Type(ButtonType.Success)
.UseSubmitBehavior(true)
);
})
.FormData(Model)
)
}
}
<script>
let formInstance;
function onInitialized(e) {
formInstance = e.component;
}
function passwordChanged(e) {
const editor = formInstance.getEditor('ConfirmPassword');
if (editor.option('value')) {
editor.element().dxValidator('validate');
}
}
function changePasswordMode(name) {
let editor = formInstance.getEditor(name);
editor.option('mode', editor.option('mode') === 'text' ? 'password' : 'text');
}
</script>
<p>The submitted data has been successfully accepted.</p>
<br />
@(Html.DevExtreme().Button()
.Text("Reload demo")
.Type(ButtonType.Default)
.Icon("refresh")
.OnClick(@<text>
function() {
window.location = window.location;
}
</text>)
)
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using DevExtreme.MVC.Demos.Models.SampleData;
using DevExtreme.MVC.Demos.ViewModels;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace DevExtreme.MVC.Demos.Controllers {
public class FormController : Controller {
[HttpGet]
public ActionResult Validation() {
return View(new EditorsViewModel() {
Name = "Peter"
});
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Validation(EditorsViewModel userInfo) {
if(ModelState.IsValid) {
return View("SuccessValidation");
}
return View(userInfo);
}
}
}
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using DevExtreme.MVC.Demos.Models.SampleData;
using System;
using System.Linq;
using System.Net.Http;
using System.Web.Http;
namespace DevExtreme.MVC.Demos.Controllers.ApiControllers {
[Route("api/GeoNames/{action}", Name = "GeoNames")]
public class GeoNamesController : ApiController {
[HttpGet]
public HttpResponseMessage Countries(DataSourceLoadOptions loadOptions) {
return Request.CreateResponse(DataSourceLoader.Load(SampleData.Countries, loadOptions));
}
[HttpGet]
public HttpResponseMessage Cities(DataSourceLoadOptions loadOptions) {
return Request.CreateResponse(DataSourceLoader.Load(SampleData.Cities, loadOptions));
}
}
}
using System;
using System.Linq;
using System.Web.Mvc;
using DevExtreme.MVC.Demos.Models.DataGrid;
namespace DevExtreme.MVC.Demos.Controllers {
public class RemoteValidationController : Controller {
InMemoryEmployeesValidationDataContext db = new InMemoryEmployeesValidationDataContext();
[HttpPost]
public JsonResult CheckUniqueEmailAddress(int? id, string email) {
bool isValid = !db.Employees.Any(emp => {
bool isEqual = string.Equals(emp.Email, email, StringComparison.OrdinalIgnoreCase);
return id != null ? id != emp.ID && isEqual : isEqual;
});
return Json(isValid);
}
[HttpPost]
public JsonResult CheckEmailAddress(string email) {
bool isInvalid = string.Equals(email, "test@dx-email.com", StringComparison.OrdinalIgnoreCase);
return Json(!isInvalid);
}
}
}
using DevExtreme.AspNet.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace DevExtreme.MVC.Demos.ViewModels {
public class EditorsViewModel {
[Required(ErrorMessage = "Email is required")]
[RegularExpression(@"^[\d\w._-]+@[\d\w._-]+\.[\w]+$", ErrorMessage = "Email is invalid")]
[Remote("CheckEmailAddress", "RemoteValidation", ErrorMessage = "Email is already registered", HttpMethod = "POST")]
public string Email { get; set; }
[Required(ErrorMessage = "Name is required")]
[RegularExpression(@"^[^0-9]+$", ErrorMessage = "Do not use digits in the Name.")]
[StringLength(int.MaxValue, MinimumLength = 2, ErrorMessage = "Name must have at least 2 symbols")]
public string Name { get; set; }
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
[Required(ErrorMessage = "Confirm Password is required")]
[System.ComponentModel.DataAnnotations.Compare("Password", ErrorMessage = "'Password' and 'Confirm Password' do not match.")]
public string ConfirmPassword { get; set; }
[RegularExpression(@"^[02-9]\d{9}$", ErrorMessage = "The phone must have a correct USA phone format")]
public string Phone { get; set; }
public string Extension { get; set; }
[Required(ErrorMessage = "Country is required")]
public string Country { get; set; }
[Required(ErrorMessage = "Address is required")]
public string Address { get; set; }
public string Description { get; set; }
public int Age { get; set; }
public string Drink { get; set; }
[Required(ErrorMessage = "City is required")]
[RegularExpression("^[^0-9]+$", ErrorMessage = "Do not use digits in the City name.")]
[StringLength(int.MaxValue, MinimumLength = 2, ErrorMessage = "City must have at least 2 symbols")]
public string City { get; set; }
public IEnumerable<string> Colors { get; set; }
public IEnumerable<string> SelectedColors { get; set; }
public string Color { get; set; }
[Display(Name = "Date of birth")]
[Required(ErrorMessage = "Date of birth is required")]
[VerifyAge(21, ErrorMessage = "You must be at least {1} years old")]
public DateTime? Date { get; set; }
[DevExtremeRequired(ErrorMessage = "You must agree to the Terms and Conditions")]
public bool Accepted { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
namespace DevExtreme.MVC.Demos.ViewModels {
public class VerifyAgeAttribute : ValidationAttribute, IClientValidatable {
public VerifyAgeAttribute(int age) {
Age = age;
}
public int Age { get; private set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
if((DateTime?)value <= DateTime.Now.AddYears(-Age)) {
return ValidationResult.Success;
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
IEnumerable<ModelClientValidationRule> IClientValidatable.GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
var rule = new ModelClientValidationRule();
rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
rule.ValidationParameters.Add(
"validationcallback",
$@"function(options) {{
var now = new Date();
return options.value && options.value <= now.setFullYear(now.getFullYear() - {Age});
}}");
rule.ValidationType = "custom";
yield return rule;
}
public override string FormatErrorMessage(string name) {
return string.Format(ErrorMessageString, name, Age);
}
}
}
form {
margin: 10px;
}