Angular Common - Data Validation
This guide provides the detailed information on validation capabilities of DevExtreme editors. It describes how to validate a single editor or a group of editors, display the validation summary, perform remote validation, use a custom validation engine, etc.
Validate an Editor Value
Associate a DevExtreme editor with the Validator UI component and specify validationRules to validate the editor. The full list of predefined validation rules is available in the Validation Rules Reference section.
jQuery
$(function () { $("#login").dxTextBox({ placeholder: 'Login' }).dxValidator({ validationRules: [{ type: 'required' }, { type: 'pattern', pattern: '^[a-zA-Z]+$', message: 'Do not use digits.' }] }); });
<div id="login"></div>
Angular
<dx-text-box [(value)]="login" placeholder="Login"> <dx-validator> <dxi-validation-rule type="required"> </dxi-validation-rule> <dxi-validation-rule type="pattern" pattern="^[a-zA-Z]+$" message="Do not use digits."> </dxi-validation-rule> </dx-validator> </dx-text-box>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { login: string; }
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { DxTextBoxModule, DxValidatorModule } from 'devextreme-angular'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, DxTextBoxModule, DxValidatorModule ], providers: [ ], bootstrap: [AppComponent] }) export class AppModule { }
Vue
<template> <DxTextBox v-model:value="login" placeholder="Login"> <DxValidator> <DxRequiredRule /> <DxPatternRule pattern="^[a-zA-Z]+$" message="Do not use digits." /> </DxValidator> </DxTextBox> </template> <script> import 'devextreme/dist/css/dx.light.css'; import DxTextBox from 'devextreme-vue/text-box'; import DxValidator, { DxRequiredRule, DxPatternRule } from 'devextreme-vue/validator'; export default { components: { DxTextBox, DxValidator, DxRequiredRule, DxPatternRule }, data() { return { login: undefined } } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.light.css'; import TextBox from 'devextreme-react/text-box'; import Validator, { RequiredRule, PatternRule } from 'devextreme-react/validator'; class App extends React.Component { constructor(props) { super(props); this.state = { login: undefined } this.setLogin = this.setLogin.bind(this); } setLogin(e) { this.setState({ login: e.value }); } render() { return ( <TextBox value={this.state.login} placeholder="Login" onValueChanged={this.setLogin}> <Validator> <RequiredRule /> <PatternRule pattern="^[a-zA-Z]+$" message="Do not use digits." /> </Validator> </TextBox> ); } } export default App;
Group the Editors
Editors belonging to a single Validation Group can be validated together. All editors on a page are automatically collected in a Default Validation Group, which is suitable when you do not need to validate collections of editors separately. In other cases, define Validation Groups as shown in the following code:
jQuery
$(function () { var loginGroup = "loginGroup"; $("#login") .dxTextBox({ /* ... */ }) .dxValidator({ // ... validationGroup: loginGroup }); $("#password") .dxTextBox({ /* ... */ }) .dxValidator({ // ... validationGroup: loginGroup }); });
<div id="login"></div> <div id="password"></div>
Angular
<dx-validation-group name="loginGroup"> <dx-text-box [(value)]="login" placeholder="Login"> <dx-validator> <!-- Login validation rules are configured here --> </dx-validator> </dx-text-box> <dx-text-box [(value)]="password" placeholder="Password"> <dx-validator> <!-- Password validation rules are configured here --> </dx-validator> </dx-text-box> </dx-validation-group>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { login: string; password: string; }
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { DxTextBoxModule, DxValidatorModule, DxValidationGroupModule } from 'devextreme-angular'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, DxTextBoxModule, DxValidatorModule, DxValidationGroupModule ], providers: [ ], bootstrap: [AppComponent] }) export class AppModule { }
Vue
<template> <DxValidationGroup name="loginGroup"> <DxTextBox v-model:value="login" placeholder="Login"> <DxValidator> <!-- Login validation rules are configured here --> </DxValidator> </DxTextBox> <DxTextBox v-model:value="password" placeholder="Password"> <DxValidator> <!-- Password validation rules are configured here --> </DxValidator> </DxTextBox> </DxValidationGroup> </template> <script> import 'devextreme/dist/css/dx.light.css'; import DxTextBox from 'devextreme-vue/text-box'; import DxValidator, { DxRequiredRule, DxPatternRule } from 'devextreme-vue/validator'; import DxValidationGroup from 'devextreme-vue/validation-group'; export default { components: { DxTextBox, DxValidator, DxRequiredRule, DxPatternRule, DxValidationGroup }, data() { return { login: undefined, password: undefined } } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.light.css'; import TextBox from 'devextreme-react/text-box'; import Validator, { // Validation rule types are imported here } from 'devextreme-react/validator'; import ValidationGroup from 'devextreme-react/validation-group'; class App extends React.Component { constructor(props) { super(props); this.state = { login: undefined, password: undefined } this.setLogin = this.setLogin.bind(this); this.setPassword = this.setPassword.bind(this); } setLogin(e) { this.setState({ login: e.value }); } setPassword(e) { this.setState({ password: e.value }); } render() { return ( <ValidationGroup name="loginGroup"> <TextBox value={this.state.login} placeholder="Login" onValueChanged={this.setLogin}> <Validator> {/* Login validation rules are configured here */} </Validator> </TextBox> <TextBox value={this.state.password} placeholder="Password" onValueChanged={this.setPassword}> <Validator> {/* Password validation rules are configured here */} </Validator> </TextBox> </ValidationGroup> ); } } export default App;
Validate the Group
Call a group's validate() method in a Button's onClick event handler to validate the group. You can access the Validation Group via the handler's argument. The Button always validates the group to which it belongs. If the membership is not specified, the Button validates the Default Validation Group.
jQuery
$(function () { // var loginGroup = "loginGroup"; $("#login") .dxTextBox({ /* ... */ }) .dxValidator({ // validationGroup: loginGroup, validationRules: [ /* ... */ ] }); $("#password") .dxTextBox({ /* ... */ }) .dxValidator({ // validationGroup: loginGroup, validationRules: [ /* ... */ ] }); $("#loginButton").dxButton({ text: "Sign in", // validationGroup: loginGroup onClick: function (e) { var result = e.validationGroup.validate(); if (result.isValid) { // ... } } }); });
<div id="login"></div> <div id="password"></div> <div id="loginButton"></div>
Angular
<!-- <dx-validation-group> --> <dx-text-box [(value)]="login"> <dx-validator> <!-- Login validation rules are configured here --> </dx-validator> </dx-text-box> <dx-text-box [(value)]="password"> <dx-validator> <!-- Password validation rules are configured here --> </dx-validator> </dx-text-box> <dx-button text="Sign in" (onClick)="signIn($event)"></dx-button> <!-- </dx-validation-group> -->
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { login: string; password: string; signIn(e) { let result = e.validationGroup.validate(); if (result.isValid) { // Submit values to the server } } }
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { DxTextBoxModule, DxValidatorModule, // DxValidationGroupModule, DxButtonModule } from 'devextreme-angular'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, DxTextBoxModule, DxValidatorModule, // DxValidationGroupModule, DxButtonModule ], providers: [ ], bootstrap: [AppComponent] }) export class AppModule { }
Vue
<template> <!-- <DxValidationGroup> --> <DxTextBox v-model:value="login" placeholder="Login"> <DxValidator> <!-- Login validation rules are configured here --> </DxValidator> </DxTextBox> <DxTextBox v-model:value="password" placeholder="Password"> <DxValidator> <!-- Password validation rules are configured here --> </DxValidator> </DxTextBox> <DxButton text="Sign in" @click="signIn" /> <!-- </DxValidationGroup> --> </template> <script> import 'devextreme/dist/css/dx.light.css'; import DxTextBox from 'devextreme-vue/text-box'; import DxValidator, { DxRequiredRule, DxPatternRule } from 'devextreme-vue/validator'; // import DxValidationGroup from 'devextreme-vue/validation-group'; import DxButton from 'devextreme-vue/button'; export default { components: { DxTextBox, DxValidator, DxRequiredRule, DxPatternRule, // DxValidationGroup, DxButton }, data() { return { login: undefined, password: undefined } }, methods: { signIn(e) { let result = e.validationGroup.validate(); if (result.isValid) { // Submit values to the server } } } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.light.css'; import TextBox from 'devextreme-react/text-box'; import Validator, { // Validation rule types are imported here } from 'devextreme-react/validator'; import ValidationGroup from 'devextreme-react/validation-group'; import Button from 'devextreme-react/button'; class App extends React.Component { constructor(props) { super(props); this.state = { login: undefined, password: undefined } this.setLogin = this.setLogin.bind(this); this.setPassword = this.setPassword.bind(this); this.signIn = this.signIn.bind(this); } setLogin(e) { this.setState({ login: e.value }); } setPassword(e) { this.setState({ password: e.value }); } signIn(e) { let result = e.validationGroup.validate(); if (result.isValid) { // Submit values to the server } } render() { return ( {/* <ValidationGroup> */} <TextBox value={this.state.login} placeholder="Login" onValueChanged={this.setLogin}> <Validator> {/* Login validation rules are configured here */} </Validator> </TextBox> <TextBox value={this.state.password} placeholder="Password" onValueChanged={this.setPassword}> <Validator> {/* Password validation rules are configured here */} </Validator> </TextBox> <Button text="Sign in" onClick={this.signIn} /> {/* </ValidationGroup> */} ); } } export default App;
jQuery
Alternatively, you can use the DevExpress.validationEngine.validateGroup method to validate a group.
$(function() { $("#login").dxTextBox({}) .dxValidator({ validationGroup: "loginGroup", validationRules: [{ type: "required" }] }); $("#password").dxTextBox({}) .dxValidator({ validationGroup: "loginGroup", validationRules: [{ type: "required" }] }); $("#button").dxButton({ text: "Sign in", onClick: function() { DevExpress.validationEngine.validateGroup("loginGroup"); } }); });
Angular
Alternatively, you can get a group's instance and call its validate method to validate this group:
<dx-validation-group #targetGroup> <dx-text-box> <dx-validator> <dxi-validation-rule type="required"> </dxi-validation-rule> </dx-validator> </dx-text-box> <dx-text-box> <dx-validator> <dxi-validation-rule type="required"> </dxi-validation-rule> </dx-validator> </dx-text-box> </dx-validation-group> <dx-button text="Sign in" (onClick)="validateGroup($event)"> </dx-button>
import { Component } from '@angular/core'; import { DxValidationGroupComponent } from 'devextreme-angular/ui/validation-group'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { @ViewChild('targetGroup', {static: false}) validationGroup: DxValidationGroupComponent validateGroup() { this.validationGroup.instance.validate(); } }
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { DxTextBoxModule, DxButtonModule, DxValidatorModule, DxValidationGroupModule } from "devextreme-angular"; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, DxButtonModule, DxTextBoxModule, DxValidatorModule, DxValidationGroupModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Vue
Alternatively, you can get a group's instance and call its validate method to validate this group:
<template> <div> <DxValidationGroup :ref="groupRefKey"> <DxTextBox> <DxValidator> <DxRequiredRule /> </DxValidator> </DxTextBox> <DxTextBox> <DxValidator> <DxRequiredRule /> </DxValidator> </DxTextBox> </DxValidationGroup> <DxButton text="Sign in" @click="validateGroup" /> </div> </template> <script> import 'devextreme/dist/css/dx.light.css'; import DxTextBox from 'devextreme-vue/text-box'; import DxValidator, { DxRequiredRule } from 'devextreme-vue/validator'; import DxValidationGroup from 'devextreme-vue/validation-group'; import DxButton from 'devextreme-vue/button'; export default { components: { DxTextBox, DxValidator, DxRequiredRule, DxValidationGroup, DxButton }, data() { groupRefKey: 'targetGroup' }, methods: { validateGroup() { this.validationGroup.validate(); } }, computed: { validationGroup: function() { return this.$refs[this.groupRefKey].instance; } } } </script>
React
Alternatively, you can get a group's instance and call its validate method to validate this group:
import React from 'react'; import 'devextreme/dist/css/dx.light.css'; import { TextBox } from 'devextreme-react/text-box'; import { Button } from 'devextreme-react/button'; import { ValidationGroup } from 'devextreme-react/validation-group'; import { Validator, RequiredRule } from 'devextreme-react/validator'; class App extends React.Component { constructor(props) { super(props); this.validateGroup = this.validateGroup.bind(this); this.validationGroup = null; }; validateGroup() { this.validationGroup.instance.validate(); } render() { return ( <React.Fragment> <ValidationGroup ref={ref => this.validationGroup = ref}> <TextBox> <Validator> <RequiredRule /> </Validator> </TextBox> <TextBox> <Validator> <RequiredRule /> </Validator> </TextBox> <Button text="Sign in" onClick={this.validateGroup} /> </ValidationGroup> <React.Fragment> ); } } export default App;
Display Validation Errors
All group validation errors can be displayed in the ValidationSummary UI component. The following code shows how to add this UI component to a page. The commented-out codelines associate the Validation Summary with a named Validation Group.
jQuery
$(function () { // var loginGroup = "loginGroup"; $("#summary").dxValidationSummary({ // validationGroup: loginGroup }); });
... <div id="summary"></div>
Angular
<!-- <dx-validation-group name="loginGroup"> --> ... <dx-validation-summary></dx-validation-summary> <!-- </dx-validation-group> -->
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { // ... // DxValidationGroupModule, DxValidationSummaryModule } from 'devextreme-angular'; @NgModule({ declarations: [ AppComponent ], imports: [ // ... // DxValidationGroupModule, DxValidationSummaryModule ], providers: [ ], bootstrap: [AppComponent] }) export class AppModule { }
Vue
<template> <!-- <DxValidationGroup name="loginGroup"> --> ... <DxValidationSummary /> <!-- </DxValidationGroup> --> </template> <script> // ... import DxValidationSummary from 'devextreme-vue/validation-summary'; // import DxValidationGroup from 'devextreme-vue/validation-group'; export default { components: { // ... // DxValidationGroup, DxValidationSummary }, // ... } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.light.css'; // ... // import ValidationGroup from 'devextreme-react/validation-group'; import ValidationSummary from 'devextreme-react/validation-summary'; class App extends React.Component { // ... render() { return ( {/* <ValidationGroup name="loginGroup"> */} ... <ValidationSummary /> {/* </ValidationGroup> */} ); } } export default App;
Disable Validation Dynamically
All the rules, except the CustomRule and AsyncRule, are always applied and cannot be disabled at runtime.
If you need to disable validation dynamically, implement a CustomRule or AsyncRule in which you should simulate the validation logic of a target rule but apply it only under certain conditions.
The following example illustrates this case. A page contains two TextBoxes and a CheckBox. The first TextBox has proper RequiredRule; the second TextBox has a CustomRule that simulates the RequiredRule logic but applies it only when the CheckBox is selected. The reevaluate property is enabled to re-check the TextBox value after the CheckBox value was changed.
jQuery
$(function() { $("#firstName").dxTextBox({ }) .dxValidator({ validationRules: [{ type: "required" }] }); $("#lastName").dxTextBox({ }) .dxValidator({ validationRules: [{ type: "custom", message: "Required", reevaluate: true, validationCallback: function(e) { if ($("#checkBox").dxCheckBox("option", "value")) { return !!e.value; } return true; } }] }); $("#validationButton").dxButton({ text: "Validate", onClick: function (params) { params.validationGroup.validate(); } }); $("#checkBox").dxCheckBox({ text: "Validate last name", value: false }); });
Angular
<dx-text-box> <dx-validator> <dxi-validation-rule type="required"> </dxi-validation-rule> </dx-validator> </dx-text-box> <dx-text-box> <dx-validator> <dxi-validation-rule type="custom" message="Required" [validationCallback]="customCallback" [reevaluate]="true"> </dxi-validation-rule> </dx-validator> </dx-text-box> <dx-button text="Validate group" (onClick)="validateGroup($event)"> </dx-button> <dx-check-box [(value)]="checkBoxValue"> </dx-check-box>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor() { this.customCallback = this.customCallback.bind(this); } checkBoxValue = false; customCallback(e) { if (this.checkBoxValue) { return !!e.value; } return true; } validateGroup(params) { params.validationGroup.validate(); } }
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { DxTextBoxModule, DxButtonModule, DxCheckBoxModule, DxValidatorModule } from "devextreme-angular"; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, DxCheckBoxModule, DxButtonModule, DxTextBoxModule, DxValidatorModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Vue
<template> <div id="root"> <DxTextBox> <DxValidator> <DxRequiredRule /> </DxValidator> </DxTextBox> <DxTextBox> <DxValidator> <DxCustomRule message="Required" :validation-callback="customCallback" :reevaluate="true" /> </DxValidator> </DxTextBox> <DxButton text="Validate group" @click="validateGroup" /> <DxCheckBox v-model:value="checkBoxValue" /> </div> </template> <script> import 'devextreme/dist/css/dx.light.css'; import { DxTextBox, DxButton, DxCheckBox } from 'devextreme-vue'; import { DxValidator, DxRequiredRule, DxCustomRule } from 'devextreme-vue/validator'; export default { components: { DxTextBox, DxButton, DxCheckBox, DxValidator, DxRequiredRule, DxCustomRule }, data() { return { checkBoxValue: false }; }, methods: { customCallback(e) { if (this.checkBoxValue) { return !!e.value; } return true; }, validateGroup(params) { params.validationGroup.validate(); } } }; </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.light.css'; import { CheckBox, TextBox, Button } from 'devextreme-react'; import { Validator, RequiredRule, CustomRule } from 'devextreme-react/validator'; class App extends React.Component { constructor(props) { super(props); this.synchronizeValues = this.synchronizeValues.bind(this); this.customCallback = this.customCallback.bind(this); this.validateGroup = this.validateGroup.bind(this); this.state = { checkBoxValue: false }; }; handleCheckBoxChange(e) { this.setState({ checkBoxValue: e.value }); } render() { return ( <div id="root"> <TextBox> <Validator> <RequiredRule /> </Validator> </TextBox> <TextBox> <Validator> <CustomRule message="Required" validationCallback={this.customCallback} reevaluate={true} /> </Validator> </TextBox> <Button text="Validate group" onClick={this.validateGroup} /> <CheckBox value={this.state.checkBoxValue} onValueChanged={this.handleCheckBoxChange} /> </div> ); } customCallback(e) { if (this.state.checkBoxValue) { return !!e.value; } return true; } validateGroup(params) { params.validationGroup.validate(); } } export default App;
Custom Validation
To implement custom validation, use the CustomRule. Refer to the validationCallback function's description for an example.
Server-Side Validation
To implement server-side validation, use the AsyncRule. Refer to the validationCallback function's description for an example.
Validate a Custom Value
You can use the DevExtreme validation engine to validate a custom value, for example, a non-DevExtreme editor value or a concatenation of several editor values, by configuring the Validator's adapter property. The following example creates two text boxes and a button. A button click checks that at least one of these text boxes is filled. Their values are provided by the getValue function.
jQuery
$(function() { var callbacks = []; var revalidate = function() { callbacks.forEach(func => { func(); }); } var phone = $("#phone").dxTextBox({ placeholder: "Phone", onValueChanged: revalidate }).dxTextBox("instance"); var email = $("#email").dxTextBox({ type: "email", placeholder: "Email", onValueChanged: revalidate }).dxTextBox("instance"); $("#validator").dxValidator({ validationRules: [{ type: "required", message: "Specify your phone or email." }], adapter: { getValue: function() { return phone.option("value") || email.option("value"); }, applyValidationResults: function(e) { $("#contacts").css({ "border": e.isValid ? "none" : "1px solid red" }); }, validationRequestsCallbacks: callbacks } }); $("#button").dxButton({ text: "Contact me", onClick: function(e) { const { isValid } = e.validationGroup.validate(); if (isValid) { // Submit values to the server } } }); $("#summary").dxValidationSummary({ }); });
<div id="contacts"> <div id="phone"></div> <div id="email"></div> </div> <div id="validator"></div> <div id="summary"></div> <div id="button"></div>
Angular
<div id="contacts" [style.border]="borderStyle"> <dx-text-box [(value)]="phone" placeholder="Phone" (onValueChanged)="revalidate()"> </dx-text-box> <dx-text-box [(value)]="email" type="email" placeholder="Email" (onValueChanged)="revalidate()"> </dx-text-box> </div> <dx-validator [adapter]="adapterConfig"> <dxi-validation-rule type="required" message="Specify your phone or email."> </dxi-validation-rule> </dx-validator> <dx-validation-summary></dx-validation-summary> <dx-button text="Contact me" (onClick)="submit($event)"> </dx-button>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { callbacks = []; phone: string; email: string; borderStyle: string = "none"; adapterConfig = { getValue: () => { return this.phone || this.email; }, applyValidationResults: (e) => { this.borderStyle = e.isValid ? "none" : "1px solid red"; }, validationRequestsCallbacks: this.callbacks }; revalidate() { this.callbacks.forEach(func => { func(); }); }; submit(e) { const { isValid } = e.validationGroup.validate(); if (isValid) { // Submit values to the server } } }
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { DxTextBoxModule, DxValidatorModule, DxValidationSummaryModule, DxButtonModule } from 'devextreme-angular'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, DxTextBoxModule, DxValidatorModule, DxValidationSummaryModule, DxButtonModule ], providers: [ ], bootstrap: [AppComponent] }) export class AppModule { }
Vue
<template> <div> <div id="contacts" :style="{ border: borderStyle }"> <DxTextBox v-model:value="phone" placeholder="Phone" @value-changed="revalidate" /> <DxTextBox v-model:value="email" placeholder="Email" @value-changed="revalidate" type="email" /> </div> <DxValidator :adapter="adapterConfig"> <DxRequiredRule message="Specify your phone or email." /> </DxValidator> <DxValidationSummary /> <DxButton text="Contact me" @click="submit" /> </div> </template> <script> import 'devextreme/dist/css/dx.light.css'; import DxTextBox from "devextreme-vue/text-box"; import DxValidator, { DxRequiredRule } from "devextreme-vue/validator"; import DxButton from "devextreme-vue/button"; import DxValidationSummary from "devextreme-vue/validation-summary"; export default { components: { DxTextBox, DxValidator, DxRequiredRule, DxButton, DxValidationSummary, }, data() { const callbacks = []; const adapterConfig = { getValue: () => { return this.phone || this.email; }, applyValidationResults: (e) => { this.borderStyle = e.isValid ? "none" : "1px solid red"; }, validationRequestsCallbacks: callbacks, }; const revalidate = () => { callbacks.forEach((func) => { func(); }); }; return { phone: undefined, email: undefined, borderStyle: "none", adapterConfig, revalidate }; }, methods: { submit (e) { const { isValid } = e.validationGroup.validate(); if (isValid) { // Submit values to the server } } }, }; </script>
React
import { useState, useCallback } from 'react'; import 'devextreme/dist/css/dx.light.css'; import { TextBox } from 'devextreme-react/text-box'; import { Button } from 'devextreme-react/button'; import { Validator, RequiredRule } from 'devextreme-react/validator'; import { ValidationSummary } from 'devextreme-react/validation-summary'; export default function App() { const [phone, setPhone] = useState(); const [email, setEmail] = useState(); const [borderStyle, setBorderStyle] = useState("none"); const callbacks = []; const adapterConfig = { getValue: () => { return phone || email; }, applyValidationResults: (e) => { setBorderStyle(e.isValid ? "none" : "1px solid red"); }, validationRequestsCallbacks: callbacks, }; const revalidate = useCallback(() => { callbacks.forEach((func) => { func(); }); }, []); const handlePhoneChange = useCallback((e) => { setPhone(e.value); revalidate(); }, []); const handleEmailChange = useCallback((e) => { setEmail(e.value); revalidate(); }, []); const submit = useCallback((e) => { const { isValid } = e.validationGroup.validate(); if (isValid) { // Submit values to the server } }, []); return ( <div> <div id="contacts" style={{ border: borderStyle }}> <TextBox value={phone} placeholder="Phone" onValueChanged={handlePhoneChange} /> <TextBox value={email} placeholder="Email" onValueChanged={handleEmailChange} type="email" /> </div> <Validator adapter={adapterConfig}> <RequiredRule message="Specify your phone or email." /> </Validator> <ValidationSummary /> <Button text="Contact me" onClick={submit} /> </div> ); }
Conditional Validation
To conditionally validate an editor, use conditional rendering on a validation rule. In the example below, the TextBox will be validated only if the SelectBox value is Germany
.
Angular
Refer to the following article for more information about conditional rendering: Adding or removing an element with NgIf.
<dx-text-box> <dx-validator> <dxi-validation-rule *ngIf="country === 'Germany'" type="required" message="Name is required" > </dxi-validation-rule> </dx-validator> </dx-text-box> <dx-select-box [dataSource]="countries" [(value)]="country" > </dx-select-box>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { countries = ['Germany', 'USA', 'China']; country = ""; }
Vue
Refer to the following article for more information about conditional rendering: Conditional Rendering.
<template> <DxTextBox> <DxValidator> <DxRequiredRule v-if="country === 'Germany'" message="Name is required" /> </DxValidator> </DxTextBox> <DxSelectBox :data-source="countries" v-model:value="country" > </DxSelectBox> </template> <script> import DxTextBox from 'devextreme-vue/text-box'; import DxSelectBox from 'devextreme-vue/select-box'; import { DxValidator, DxRequiredRule } from 'devextreme-vue/validator'; export default { components: { DxTextBox, DxSelectBox, DxValidator, DxRequiredRule }, data() { return { countries: ['Germany', 'USA', 'China'], country: '' } } } </script>
React
Refer to the following article for more information about conditional rendering: Conditional Rendering.
import React, { useState, useCallback } from "react"; import TextBox from "devextreme-react/text-box"; import SelectBox from "devextreme-react/select-box"; import { Validator, RequiredRule } from "devextreme-react/validator"; const countries = ['Germany', 'USA', 'China']; function App() { const [country, setCountry] = useState(""); const onCountryChanged = useCallback((e) => { setCountry(e.value); }, []); return ( <React.Fragment> <TextBox> <Validator> {country === "Germany" && <RequiredRule message="Name is required" />} </Validator> </TextBox> <SelectBox dataSource={countries} value={country} onValueChanged={onCountryChanged} /> </React.Fragment> ); } export default App;
Knockout Only - Validate a View Model
Validating the view model object rather than the editors allows you to separate validation logic from the UI, reuse it between multiple views and unit-test the implementation. To validate a view model's observable, extend it with an object whose dxValidator field contains the validator configuration. After that, associate a target editor with the validator using the isValid and validationError properties.
$(function () { var viewModel = { login: ko.observable("").extend({ dxValidator: { validationRules: [{ type: 'required', message: 'Login is required' }] } }), password: ko.observable("").extend({ dxValidator: { name: "Password", validationRules: [{ type: 'required' }] } }) }; ko.applyBindings(viewModel); });
<div data-bind="dxTextBox: { value: login, placeholder: 'Login', isValid: login.dxValidator.isValid, validationError: login.dxValidator.validationError }"></div> <div data-bind="dxTextBox: { value: password, mode: 'password', placeholder: 'Password', isValid: password.dxValidator.isValid, validationError: password.dxValidator.validationError }"></div>
Finally, pass the to the DevExpress.validationEngine.registerModelForValidation(model) method to register it in the validation engine. The registered view model can be validated at any point in your application by calling the DevExpress.validationEngine.validateModel(model) method.
var viewModel = { //... validateAndLogin: function (params) { var result = DevExpress.validationEngine.validateModel(this); if (result.isValid) { // ... } } }; DevExpress.validationEngine.registerModelForValidation(viewModel); ko.applyBindings(viewModel);
If you have technical questions, please create a support ticket in the DevExpress Support Center.