@using DevExtreme.NETCore.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)
.InputAttr("aria-label", "Password")
.OnValueChanged("passwordChanged")
.Buttons(buttons => {
buttons.Add()
.Name("password")
.Location(TextEditorButtonLocation.After)
.Widget(w => w.Button()
.Type(ButtonType.Default)
.Icon(Url.Content("~/images/icons/eye.png"))
.OnClick("() => changePasswordMode('Password')"));
})
);
groupItems.AddSimpleFor(m => m.ConfirmPassword)
.Editor(e => e.TextBox()
.Mode(TextBoxMode.Password)
.InputAttr("aria-label", "Password")
.Buttons(buttons => {
buttons.Add()
.Name("password")
.Location(TextEditorButtonLocation.After)
.Widget(w => w.Button()
.Type(ButtonType.Default)
.Icon(Url.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()
.InputAttr("aria-label", "Country")
.DataSource(d => d.Mvc().Controller("GeoNames").LoadAction("Countries"))
);
groupItems.AddSimpleFor(m => m.City)
.Editor(e => e
.Autocomplete()
.MinSearchLength(2)
.DataSource(d => d.Mvc().Controller("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")
.InputAttr("aria-label", "Phone")
.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.NETCore.Demos.Models.SampleData;
using DevExtreme.NETCore.Demos.ViewModels;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.NETCore.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.NETCore.Demos.Models.SampleData;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Linq;
using System.Net.Http;
namespace DevExtreme.NETCore.Demos.Controllers.ApiControllers {
[Route("api/[controller]/[action]")]
public class GeoNamesController : Controller {
[HttpGet]
public object Countries(DataSourceLoadOptions loadOptions) {
return DataSourceLoader.Load(SampleData.Countries, loadOptions);
}
[HttpGet]
public object Cities(DataSourceLoadOptions loadOptions) {
return DataSourceLoader.Load(SampleData.Cities, loadOptions);
}
}
}
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using DevExtreme.NETCore.Demos.Models.DataGrid;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
namespace DevExtreme.NETCore.Demos.Controllers {
public class RemoteValidationController : Controller {
InMemoryEmployeesValidationDataContext _db;
public RemoteValidationController(IHttpContextAccessor httpContextAccessor, IMemoryCache memoryCache) {
_db = new InMemoryEmployeesValidationDataContext(httpContextAccessor, memoryCache);
}
[HttpPost]
public JsonResult CheckUniqueEmailAddress([FromBody] JObject data) {
int? id = (int?)data["id"];
string email = data["email"].ToString();
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 Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace DevExtreme.NETCore.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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace DevExtreme.NETCore.Demos.ViewModels {
public class VerifyAgeAttribute : ValidationAttribute, IClientModelValidator {
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));
}
void IClientModelValidator.AddValidation(ClientModelValidationContext context) {
context.Attributes.Add("data-val-custom-verifyage", FormatErrorMessage(context.ModelMetadata.GetDisplayName()));
context.Attributes.Add(
"data-val-custom-verifyage-validationcallback",
$@"function(options) {{
var now = new Date();
return options.value && options.value <= now.setFullYear(now.getFullYear() - {Age});
}}");
}
public override string FormatErrorMessage(string name) {
return string.Format(ErrorMessageString, name, Age);
}
}
}
form {
margin: 10px;
}