<form action="your-action" (submit)="onFormSubmit($event)">
<div class="dx-fieldset">
<div class="dx-fieldset-header">Credentials</div>
<div class="dx-field">
<div class="dx-field-label">Email</div>
<div class="dx-field-value">
<dx-text-box>
<dx-validator>
<dxi-validation-rule type="required" message="Email is required"></dxi-validation-rule>
<dxi-validation-rule type="email" message="Email is invalid"></dxi-validation-rule>
<dxi-validation-rule type="async" message="Email is already registered" [validationCallback]="asyncValidation"></dxi-validation-rule>
</dx-validator>
</dx-text-box>
</div>
</div>
<div class="dx-field">
<div class="dx-field-label">Password</div>
<div class="dx-field-value">
<dx-text-box
mode="password"
[(value)]="password">
<dx-validator>
<dxi-validation-rule type="required" message="Password is required"></dxi-validation-rule>
</dx-validator>
</dx-text-box>
</div>
</div>
<div class="dx-field">
<div class="dx-field-label">Confirm Password</div>
<div class="dx-field-value">
<dx-text-box mode="password">
<dx-validator>
<dxi-validation-rule type="required" message="Confirm Password is required"></dxi-validation-rule>
<dxi-validation-rule type="compare" [comparisonTarget]="passwordComparison"
message="Password and Confirm Password do not match"></dxi-validation-rule>
</dx-validator>
</dx-text-box>
</div>
</div>
</div>
<div class="dx-fieldset">
<div class="dx-fieldset-header">Personal Data</div>
<div class="dx-field">
<div class="dx-field-label">Name</div>
<div class="dx-field-value">
<dx-text-box value="Peter">
<dx-validator>
<dxi-validation-rule type="required" message="Name is required"></dxi-validation-rule>
<dxi-validation-rule type="pattern" [pattern]="namePattern" message="Do not use digits in the Name"></dxi-validation-rule>
<dxi-validation-rule type="stringLength" [min]="2" message="Name must have at least 2 symbols"></dxi-validation-rule>
</dx-validator>
</dx-text-box>
</div>
</div>
<div class="dx-field">
<div class="dx-field-label">Date of birth</div>
<div class="dx-field-value">
<dx-date-box
invalidDateMessage="The date must have the following format: MM/dd/yyyy">
<dx-validator>
<dxi-validation-rule type="required" message="Date of birth is required"></dxi-validation-rule>
<dxi-validation-rule type="range" [max]="maxDate" message="You must be at least 21 years old"></dxi-validation-rule>
</dx-validator>
</dx-date-box>
</div>
</div>
</div>
<div class="dx-fieldset">
<div class="dx-fieldset-header">Billing address</div>
<div class="dx-field">
<div class="dx-field-label">Country</div>
<div class="dx-field-value">
<dx-select-box [dataSource]="countries">
<dx-validator>
<dxi-validation-rule type="required" message="Country is required"></dxi-validation-rule>
</dx-validator>
</dx-select-box>
</div>
</div>
<div class="dx-field">
<div class="dx-field-label">City</div>
<div class="dx-field-value">
<dx-text-box>
<dx-validator>
<dxi-validation-rule type="required" message="City is required"></dxi-validation-rule>
<dxi-validation-rule type="pattern" [pattern]="cityPattern" message="Do not use digits in the City name"></dxi-validation-rule>
<dxi-validation-rule type="stringLength" [min]="2" message="City must have at least 2 symbols"></dxi-validation-rule>
</dx-validator>
</dx-text-box>
</div>
</div>
<div class="dx-field">
<div class="dx-field-label">Address</div>
<div class="dx-field-value">
<dx-text-box>
<dx-validator>
<dxi-validation-rule type="required" message="Address is required"></dxi-validation-rule>
</dx-validator>
</dx-text-box>
</div>
</div>
<div class="dx-field">
<div class="dx-field-label">Phone <i>(optional)</i></div>
<div class="dx-field-value">
<dx-text-box
mask="+1 (X00) 000-0000"
[maskRules]="phoneRules"
maskInvalidMessage="The phone must have a correct USA phone format"
[useMaskedValue]="true">
<dx-validator>
<dxi-validation-rule type="pattern" [pattern]="phonePattern" message="The phone must have a correct USA phone format"></dxi-validation-rule>
</dx-validator>
</dx-text-box>
</div>
</div>
<div>
<dx-check-box
id="check"
[value]="false"
text="I agree to the Terms and Conditions">
<dx-validator>
<dxi-validation-rule type="compare" [comparisonTarget]="checkComparison" message="You must agree to the Terms and Conditions"></dxi-validation-rule>
</dx-validator>
</dx-check-box>
</div>
</div>
<div class="dx-fieldset">
<dx-validation-summary id="summary"></dx-validation-summary>
<dx-button
id="button"
text="Register"
type="success"
[useSubmitBehavior]="true">
</dx-button>
</div>
</form>
import { Component, NgModule, enableProdMode } from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {DxSelectBoxModule,
DxCheckBoxModule,
DxTextBoxModule,
DxDateBoxModule,
DxButtonModule,
DxValidatorModule,
DxValidationSummaryModule} from 'devextreme-angular';
import notify from 'devextreme/ui/notify';
import { Service } from './app.service';
if(!/localhost/.test(document.location.host)) {
enableProdMode();
}
const sendRequest = function(value) {
const validEmail = "test@dx-email.com";
return new Promise((resolve) => {
setTimeout(function() {
resolve(value === validEmail);
}, 1000);
});
}
@Component({
selector: 'demo-app',
providers: [Service],
templateUrl: 'app/app.component.html',
styleUrls: ['app/app.component.css']
})
export class AppComponent {
password = "";
maxDate: Date = new Date();
cityPattern = "^[^0-9]+$";
namePattern: any = /^[^0-9]+$/;
phonePattern: any = /^\+\s*1\s*\(\s*[02-9]\d{2}\)\s*\d{3}\s*-\s*\d{4}$/;
countries: string[];
phoneRules: any = {
X: /[02-9]/
}
constructor(service: Service) {
this.maxDate = new Date(this.maxDate.setFullYear(this.maxDate.getFullYear() - 21));
this.countries = service.getCountries();
}
passwordComparison = () => {
return this.password;
};
checkComparison() {
return true;
}
asyncValidation(params) {
return sendRequest(params.value);
}
onFormSubmit = function(e) {
notify({
message: "You have submitted the form",
position: {
my: "center top",
at: "center top"
}
}, "success", 3000);
e.preventDefault();
}
}
@NgModule({
imports: [
BrowserModule,
DxSelectBoxModule,
DxCheckBoxModule,
DxTextBoxModule,
DxDateBoxModule,
DxButtonModule,
DxValidatorModule,
DxValidationSummaryModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);
::ng-deep #summary {
padding-left: 10px;
margin-top: 20px;
margin-bottom: 10px;
}
::ng-deep #button {
display: block;
}
import { Injectable } from '@angular/core';
let countries: string[] = [
'Afghanistan','Albania','Algeria','Andorra','Angola','Antigua and Barbuda','Argentina','Armenia','Australia','Austria','Azerbaijan','The Bahamas','Bahrain','Bangladesh','Barbados','Belarus','Belgium','Belize','Benin','Bhutan','Bolivia','Bosnia and Herzegovina','Botswana','Brazil','Brunei','Bulgaria','Burkina Faso','Burma','Burundi','Cambodia','Cameroon','Canada','Cape Verde','Central African Republic','Chad','Chile','China','Colombia','Comoros','Democratic Republic of the Congo','Republic of the Congo','Costa Rica','Ivory Coast','Croatia','Cuba','Cyprus','Czech Republic','Denmark','Djibouti','Dominica','Dominican Republic','East Timor','Ecuador','Egypt','El Salvador','Equatorial Guinea','Eritrea','Estonia','Ethiopia','Fiji','Finland','France','Gabon','The Gambia','Georgia','Germany','Ghana','Greece','Grenada','Guatemala','Guinea','Guinea-Bissau','Guyana','Haiti','Honduras','Hungary','Iceland','India','Indonesia','Iran','Iraq','Republic of Ireland','Israel','Italy','Jamaica','Japan','Jordan','Kazakhstan','Kenya','Kiribati','North Korea','South Korea','Kuwait','Kyrgyzstan','Laos','Latvia','Lebanon','Lesotho','Liberia','Libya','Liechtenstein','Lithuania','Luxembourg','Republic of Macedonia','Madagascar','Malawi','Malaysia','Maldives','Mali','Malta','Marshall Islands','Mauritania','Mauritius','Mexico','Federated States of Micronesia','Moldova','Monaco','Mongolia','Montenegro','Morocco','Mozambique','Namibia','Nauru','Nepal','Kingdom of the Netherlands','New Zealand','Nicaragua','Niger','Nigeria','Norway','Oman','Pakistan','Palau','State of Palestine','Panama','Papua New Guinea','Paraguay','Peru','Philippines','Poland','Portugal','Qatar','Romania','Russia','Rwanda','Saint Kitts and Nevis','Saint Lucia','Saint Vincent and the Grenadines','Samoa','San Marino','São Tomé and Príncipe','Saudi Arabia','Senegal','Serbia','Seychelles','Sierra Leone','Singapore','Slovakia','Slovenia','Solomon Islands','Somalia','South Africa','South Sudan','Spain','Sri Lanka','Sudan','Suriname','Swaziland','Sweden','Switzerland','Syria','Tajikistan','Tanzania','Thailand','Togo','Tonga','Trinidad and Tobago','Tunisia','Turkey','Turkmenistan','Tuvalu','Uganda','Ukraine','United Arab Emirates','United Kingdom','United States','Uruguay','Uzbekistan','Vanuatu','Vatican City','Venezuela','Vietnam','Yemen','Zambia','Zimbabwe'];
@Injectable()
export class Service {
getCountries() {
return countries;
}
}
// In real applications, you should not transpile code in the browser. You can see how to create your own application with Angular and DevExtreme here:
// https://js.devexpress.com/Documentation/Guide/Angular_Components/Getting_Started/Create_a_DevExtreme_Application/
System.config({
transpiler: 'ts',
typescriptOptions: {
module: "system",
emitDecoratorMetadata: true,
experimentalDecorators: true
},
meta: {
'typescript': {
"exports": "ts"
},
'devextreme/localization.js': {
"esModule": true
}
},
paths: {
'npm:': 'https://unpkg.com/'
},
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@3.5.3/lib/typescript.js',
'@angular': 'npm:@angular',
'tslib': 'npm:tslib@2.0.3/tslib.js',
'rxjs': 'npm:rxjs@6.3.3',
'rrule': 'npm:rrule@2.6.6/dist/es5/rrule.js',
'luxon': 'npm:luxon@1.25.0/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign@1.1.0',
'devextreme': 'npm:devextreme@20.2.4',
'jszip': 'npm:jszip@3.5.0/dist/jszip.min.js',
'devextreme-quill': 'npm:devextreme-quill@0.9.7/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.0.5',
'devexpress-gantt': 'npm:devexpress-gantt@2.0.8',
'devextreme-angular': 'npm:devextreme-angular@20.2.4',
'preact': 'npm:preact@10.5.7/dist/preact.js',
'preact/hooks': 'npm:preact@10.5.7/hooks/dist/hooks.js'
},
packages: {
'app': {
main: './app.component.ts',
defaultExtension: 'ts'
},
'devextreme': {
defaultExtension: 'js'
},
'devextreme/events/utils': {
main: 'index'
},
'devextreme/events': {
main: 'index'
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js'
}
},
packageConfigPaths: [
"npm:@angular/*/package.json",
"npm:@angular/common/*/package.json",
"npm:rxjs/package.json",
"npm:rxjs/operators/package.json",
"npm:devextreme-angular/*/package.json",
"npm:devextreme-angular/ui/*/package.json",
"npm:devextreme-angular/package.json",
"npm:devexpress-diagram/package.json",
"npm:devexpress-gantt/package.json",
]
});
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/20.2.4/css/dx.common.css" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/20.2.4/css/dx.light.css" />
<script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.10.2/dist/zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app').catch(console.error.bind(console));
</script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<demo-app>Loading...</demo-app>
</div>
</body>
</html>