Angular Validator - AsyncRule

A custom validation rule that is checked asynchronously. Use async rules for server-side validation.

import { AsyncRule } from "devextreme/common"
Type:

Object

To specify the async rule, set the type to "async" and declare the validationCallback function.

You can also set a custom message, specify whether empty values are valid, and whether the rule should be re-evaluated, even if the target value is the same.

Validation rules are checked in the following order: All the synchronous rules are checked in the same order as in the validationRules array. Then, all the async rules are checked simultaneously.

View Demo

See Also

ignoreEmptyValue

If true, the validationCallback is not executed for null, undefined, false, and empty strings.

Type:

Boolean

Default Value: false

message

Specifies the message that is shown if the rule is broken.

Type:

String

Default Value: 'Value is invalid'

An error message can be specified as follows:

  • Hard-code the message

    jQuery
    index.js
    $(function() {
        $("#textBox").dxTextBox({ ... })
            .dxValidator({
                type: "async",
                message: "My custom message"
            });
    });
    Angular
    app.component.html
    app.module.ts
    <dx-text-box> 
        <dx-validator>
            <dxi-validation-rule 
                type="async" 
                message="My custom message">
            </dxi-validation-rule>
        </dx-validator>
    </dx-text-box>
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    
    import { DxValidatorModule,
             DxTextBoxModule } from 'devextreme-angular';
    
    @NgModule({
        declarations: [
            AppComponent
        ],
        imports: [
            DxTextBoxModule,
            BrowserModule,
            DxValidatorModule
        ],
        providers: [],
        bootstrap: [AppComponent]
    })
    export class AppModule { }
    Vue
    App.vue
    <template>
        <DxTextBox>
            <DxValidator>
                <DxAsyncRule
                    message="My custom message"
                />
            </DxValidator>
        </DxTextBox>
    </template>
    
    <script>
    import 'devextreme/dist/css/dx.light.css';
    
    import { DxTextBox } from 'devextreme-vue/text-box';
    import {
        DxValidator,
        DxAsyncRule
    } from 'devextreme-vue/validator';
    
    export default {
        components: {
            DxTextBox,
            DxValidator,
            DxAsyncRule
        }
    }
    </script>
    React
    App.js
    import React from 'react';
    
    import 'devextreme/dist/css/dx.light.css';
    
    import { TextBox } from 'devextreme-react/text-box';
    import {
        Validator,
        AsyncRule
    } from 'devextreme-react/validator';
    
    class App extends React.Component {
        render() {
            return (
                <TextBox>
                    <Validator>
                        <AsyncRule
                            message="My custom message" />
                    </Validator>
                </TextBox>
            );
        }
    }
    export default App;
  • Hide the message

    jQuery
    index.js
    $(function() {
        $("#textBox").dxTextBox({ ... })
            .dxValidator({
                type: "async",
                message: ""
            });
    });
    Angular
    app.component.html
    app.module.ts
    <dx-text-box>
        <dx-validator>
            <dxi-validation-rule 
                type="async" 
                message="">
            </dxi-validation-rule>
        </dx-validator>
    </dx-text-box>
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    
     import { DxValidatorModule,
              DxTextBoxModule } from 'devextreme-angular';
    
    @NgModule({
        declarations: [
            AppComponent
        ],
        imports: [
            BrowserModule,
            DxValidatorModule,
            DxTextBoxModule
        ],
        providers: [],
        bootstrap: [AppComponent]
    })
    export class AppModule { }
    Vue
    App.vue
    <template>
        <DxTextBox>
            <DxValidator>
                <DxAsyncRule
                    message=""
                />
            </DxValidator>
        </DxTextBox>
    </template>
    
    <script>
    import 'devextreme/dist/css/dx.light.css';
    
    import { DxTextBox } from 'devextreme-vue/text-box';
    import {
        DxValidator,
        DxAsyncRule
    } from 'devextreme-vue/validator';
    
    export default {
        components: {
            DxTextBox,
            DxValidator,
            DxAsyncRule
        }
    }
    </script>
    React
    App.js
    import React from 'react';
    
    import 'devextreme/dist/css/dx.light.css';
    
    import { TextBox } from 'devextreme-react/text-box';
    import {
        Validator,
        AsyncRule
    } from 'devextreme-react/validator';
    
    class App extends React.Component {
        render() {
            return (
                <TextBox>
                    <Validator>
                        <AsyncRule
                            message="" />
                    </Validator>
                </TextBox>
            );
        }
    }
    export default App;
  • Display the editor's name in the message

    jQuery
    index.js
    $(function() {
        $("#textBox").dxTextBox({ ... })
            .dxValidator({
                name: "Password", // The error message will be "Password is invalid"
                validationRules: [{
                    type: "async"
                }]
            });
    });
    Angular
    app.component.html
    app.module.ts
    <dx-text-box>
        <!-- The error message will be "Password is invalid" -->
        <dx-validator name="Password">
            <dxi-validation-rule 
                type="async">
            </dxi-validation-rule>
        </dx-validator>
    </dx-text-box>
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    
    import { DxValidatorModule,
             DxTextBoxModule } from 'devextreme-angular';
    
    @NgModule({
        declarations: [
            AppComponent
        ],
        imports: [
            BrowserModule,
            DxValidatorModule,
            DxTextBoxModule
        ],
        providers: [],
        bootstrap: [AppComponent]
    })
    export class AppModule { }
    Vue
    App.vue
    <template>
        <DxTextBox>
            <!-- The error message will be "Password is invalid" -->
            <DxValidator name="Password">
                <DxAsyncRule />
            </DxValidator>
        </DxTextBox>
    </template>
    
    <script>
    import 'devextreme/dist/css/dx.light.css';
    
    import { DxTextBox } from 'devextreme-vue/text-box';
    import {
        DxValidator,
        DxAsyncRule
    } from 'devextreme-vue/validator';
    
    export default {
        components: {
            DxValidator,
            DxAsyncRule
        }
    }
    </script>
    React
    App.js
    import React from 'react';
    
    import 'devextreme/dist/css/dx.light.css';
    
    import { TextBox } from 'devextreme-react/text-box';
    import {
        Validator,
        AsyncRule
    } from 'devextreme-react/validator';
    
    class App extends React.Component {
        render() {
            return (
                <TextBox>
                    {/* The error message will be "Password is invalid" */}
                    <Validator name="Password">
                        <AsyncRule} />
                    </Validator>
                </TextBox>
            );
        }
    }
    
    export default App;
  • Get the message from the server
    See the example in the validationCallback description.

reevaluate

Indicates whether the rule should always be checked for the target value or only when the value changes.

Type:

Boolean

Default Value: true

type

Specifies the rule type. Set it to "async" to use the AsyncRule.

validationCallback

A function that validates the target value.

Type:

Function

Function parameters:
options:

Object

An object that defines validation parameters.

Object structure:
Name Type Description
column

Object

The column to which the cell being validated belongs. Exists only when you validate a built-in editor in the DataGrid or TreeList.

data

Object

The current row's data. Exists only when you validate a DataGrid or TreeList cell's value.

formItem

Object

The form item being validated. Exists only when you validate a built-in editor in the Form UI component.

rule

Object

The rule being checked.

validator

Object

The Validator object that initiated the validation.

value

String

|

Number

The validated value.

Return Value:

Promise<any> (jQuery or native)

A Promise that should be resolved or rejected as shown in the example below.

The following code shows a generic validationCallback implementation for a server that returns a JSON response. The function sends the value that should be validated to the server. The response includes a flag that indicates validity, and optionally an error message that is used if validation fails.

jQuery
index.js
$(function() {
    $("#textBox").dxTextBox({ ... })
        .dxValidator({
            validationRules: [{ 
                type: "async", 
                validationCallback: function(params) {
                    const d = $.Deferred();
                    $.ajax( ... ).done(function(res) {
                        // res.message contains validation error message
                        res.isValid ? d.resolve() : d.reject(res.message);

                        // ===== or if "res" is { isValid: Boolean, message: String } =====
                        d.resolve(res);
                    }).fail(function(error) {
                        console.error("Server-side validation error", error);

                        d.reject("Cannot contact validation server");
                    })
                    return d.promise();
                }
            }]
        });
});
Angular
app.component.html
app.component.ts
app.module.ts
<dx-text-box>
    <dx-validator>
        <dxi-validation-rule type="async" 
            [validationCallback]="validateAsync">
        </dxi-validation-rule>
    </dx-validator>
</dx-text-box>
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { lastValueFrom } from 'rxjs';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    constructor(private httpClient: HttpClient) {
        this.validateAsync = this.validateAsync.bind(this);
    }

    validateAsync(params) {
        return new Promise(async (resolve, reject) => {
            try {
                const res: any = await lastValueFrom(this.httpClient.post("https://mydomain.com/MyDataService", { data: params.value }));
                // res.message contains validation error message
                res.isValid ? resolve() : reject(res.message);
                // ===== or if "res" is { isValid: Boolean, message: String } =====
                // resolve(res);
            } catch (error) {
                console.error("Server-side validation error", error);
                reject("Cannot contact validation server");
            }
        });
    }
}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

import { DxValidatorModule,
        DxTextBoxModule } from 'devextreme-angular';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        HttpClientModule,
        DxTextBoxModule,
        DxValidatorModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }
Vue
App.vue
<template>
    <DxTextBox>
        <DxValidator>
            <DxAsyncRule
                :validation-callback="validateAsync"
            />
        </DxValidator>
    </DxTextBox>
</template>

<script>
import 'devextreme/dist/css/dx.light.css';

import { DxTextBox } from 'devextreme-vue/text-box';
import {
    DxValidator,
    DxAsyncRule
} from 'devextreme-vue/validator';
import 'whatwg-fetch';

export default {
    components: {
        DxTextBox,
        DxValidator,
        DxAsyncRule
    },
    methods: {
        validateAsync(params) {
            return new Promise((resolve, reject) => {
                fetch("https://mydomain.com/MyDataService", {
                    method: 'POST',
                    body: JSON.stringify({ data: params.value })
                })
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error: ${res.status} ${res.statusText}`);
                    }
                    return response.json();
                })
                .then(res => {
                    // res.message contains validation error message
                    res.isValid ? resolve() : reject(res.message);

                    // ===== or if "res" is { isValid: Boolean, message: String } =====
                    resolve(res);
                })
                .catch(error => {
                    console.error("Server-side validation error", error);

                    reject("Cannot contact validation server");
                });
            });
        }
    }
}
</script>
React
App.js
import React from 'react';

import 'devextreme/dist/css/dx.light.css';

import { TextBox } from 'devextreme-react/text-box';
import {
    Validator,
    AsyncRule
} from 'devextreme-react/validator';
import 'whatwg-fetch';

const validateAsync = function(params) {
    return new Promise((resolve, reject) => {
        fetch("https://mydomain.com/MyDataService", {
            method: 'POST',
            body: JSON.stringify({ data: params.value })
        })
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error: ${res.status} ${res.statusText}`);
            }
            return response.json();
        })
        .then(res => {
            // res.message contains validation error message
            res.isValid ? resolve() : reject(res.message);

            // ===== or if "res" is { isValid: Boolean, message: String } =====
            resolve(res);
        })
        .catch(error => {
            console.error("Server-side validation error", error);

            reject("Cannot contact validation server");
        });
    });
};

class App extends React.Component {
    render() {
        return (
            <TextBox>
                <Validator>
                    <AsyncRule
                        validationCallback={validateAsync} />
                </Validator>
            </TextBox>
        );
    }
}
export default App;