Skip to content

Commit bcc3147

Browse files
committed
Added custom form validations
1 parent e43e8fc commit bcc3147

File tree

10 files changed

+133
-16
lines changed

10 files changed

+133
-16
lines changed

src/app/modules/examples/components/contact-form/contact-form.component.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<div class="contact-form">
2+
<h1>Contact me !</h1>
23
<div class="contact-mobile-number">
4+
<label>Phone number: </label>
35
<app-mobile-number [group]="contactForm"
46
[contryCode]="contactForm.controls['contryCode']"
57
[mobileNumber]="contactForm.controls['mobileNumber']"></app-mobile-number>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
@import '../../../../../assets/scss/_variable';
2+
13
.contact-form {
24
padding: 20px;
5+
display: grid;
6+
align-content: center;
7+
justify-content: center;
8+
text-align: center;
9+
height: $content-height;
310
}

src/app/modules/examples/components/contact-form/contact-form.component.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Component, OnInit } from '@angular/core';
2-
import { FormControl, FormGroup, Validators } from '@angular/forms';
2+
import { FormControl, FormGroup } from '@angular/forms';
3+
import { UtilityFunctions } from 'src/app/utilities/app.utility';
34

45
@Component({
56
selector: 'app-contact-form',
@@ -10,16 +11,23 @@ export class ContactFormComponent implements OnInit {
1011

1112
contactForm: FormGroup;
1213

13-
constructor() { }
14+
constructor(
15+
private util: UtilityFunctions
16+
) { }
1417

1518
ngOnInit(): void {
1619
this.initialise();
1720
}
1821

1922
initialise() {
2023
this.contactForm = new FormGroup ({
21-
mobileNumber: new FormControl('', [Validators.required, Validators.maxLength(15), Validators.minLength(6)]),
22-
contryCode: new FormControl('', Validators.required),
24+
mobileNumber: new FormControl('', [
25+
this.util.requiredValidator('phone number'),
26+
this.util.minlengthValidator('Phone number', 6),
27+
this.util.maxlengthValidator('Phone number', 15),
28+
this.util.onlyNumberValidator('phone number')
29+
]),
30+
contryCode: new FormControl('', this.util.requiredValidator('phone code')),
2331
});
2432
}
2533

src/app/shared/ui-components/input/input.component.html

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,11 @@
2222
autocomplete="off"
2323
(blur)="blur()" />
2424
<mat-error *ngIf="control.touched && control.invalid">
25-
{{
26-
(control.errors.required) ? "Please enter "+name.toLowerCase() :
27-
(control.errors.minlength) ? name + " must be greater than " + (control.errors.minlength.requiredLength-1) :
28-
(control.errors.maxlength) ? name + " must be lesser than " + control.errors.maxlength.requiredLength :
29-
(control.errors.incorrect) ? control.errors.incorrect : ''
30-
}}
25+
<!-- Easy way to display any kind of error in HTML
26+
-> Get the first error key and display the error string in it-->
27+
{{ control.errors[objectFn.keys(control.errors)[0]] }}
3128
</mat-error>
3229
</mat-form-field>
3330
</div>
34-
</ng-container>
31+
</ng-container>
3532

src/app/shared/ui-components/input/input.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ export class InputComponent implements OnInit {
4343
// tslint:disable-next-line: no-output-on-prefix
4444
@Output() onBlur: EventEmitter<boolean>;
4545

46+
// HTML helpers
47+
objectFn = Object;
48+
4649
ngOnInit() { }
4750

4851
blur() {

src/app/shared/ui-components/mobile-number/mobile-number.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="mobile-number">
22
<div class="mobile-code">
33
<mat-form-field [formGroup]="group" class="mobile-code-form">
4-
<mat-select placeholder="" #singleSelect name="countryCodeNum" [formControl]="contryCode">
4+
<mat-select placeholder="Phone code" #singleSelect name="countryCodeNum" [formControl]="contryCode">
55
<mat-option>
66
<ngx-mat-select-search [formControl]="countryCodeSearchVal"
77
placeholderLabel="Search phone code"

src/app/shared/ui-components/mobile-number/mobile-number.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export class MobileNumberComponent implements OnInit {
5656
this.countryCodeSearchVal = new FormControl('');
5757
}
5858

59+
/* Function to check phone number validity */
5960
isPhoneValid(codeName = null) {
6061
if (codeName) {
6162
this.selectedCodeName = codeName;

src/app/utilities/app.utility.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Injectable } from '@angular/core';
2+
import { FormControl } from '@angular/forms';
23

34
@Injectable({
45
providedIn: 'root',
@@ -25,4 +26,98 @@ export class UtilityFunctions {
2526
}
2627
}
2728

29+
/**
30+
* Custom form validators
31+
* @Description Below functions are used intead for actual form controls.
32+
* Because we can customise error messages accordingly here
33+
* rather than having to handing in HTML for each field.
34+
* We can customise a lot.
35+
*/
36+
// Required validator function
37+
public requiredValidator(fieldName: string = '', type: 'select' | 'input' = 'input') {
38+
return (control: FormControl) => {
39+
const name = (control.value) ? control.value.toString() : '';
40+
if (!name || !name.trim() || name.trim() === '') {
41+
if (type === 'select') {
42+
return {
43+
required: 'Please choose your ' + fieldName
44+
};
45+
} else {
46+
return {
47+
required: 'Please enter your ' + fieldName
48+
};
49+
}
50+
}
51+
return null;
52+
};
53+
}
54+
55+
// Required validator function
56+
public maxlengthValidator(fieldName: string = '', length: number) {
57+
return (control: FormControl) => {
58+
const name = (control.value) ? control.value.toString() : '';
59+
if (name && !name.trim() || name.trim() === '' || (length && name.length < (length))) {
60+
return {
61+
maxlength: `${fieldName} can't be greater than ${length} characters`
62+
};
63+
}
64+
return null;
65+
};
66+
}
67+
68+
// Required validator function
69+
public minlengthValidator(fieldName: string = '', length: number) {
70+
return (control: FormControl) => {
71+
const name = (control.value) ? control.value.toString() : '';
72+
if (name && !name.trim() || name.trim() === '' || (length && name.length > (length))) {
73+
return {
74+
minlength: `${fieldName} can't be lesser than ${length} characters`
75+
};
76+
}
77+
return null;
78+
};
79+
}
80+
81+
// Email form control validator function
82+
public emailValidator = (fieldName: string = 'email address') => {
83+
return (control: FormControl) => {
84+
const email = (control.value) ? control.value.toString() : '';
85+
const regex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
86+
if (email && !regex.test(email)) {
87+
return {
88+
email: 'Please enter a valid ' + fieldName
89+
};
90+
}
91+
return null;
92+
};
93+
}
94+
95+
// Only alpha numeric name validator
96+
public onlyAlphaNameValidator(fieldName: string = '') {
97+
return (control: FormControl) => {
98+
const name = control.value;
99+
const regex = /^[a-zA-Z_\ ]*$/;
100+
if (name && !regex.test(name)) {
101+
return {
102+
onlyAlphaName: 'Please enter a valid ' + fieldName + '. Only aplabets, space and _ are allowed.'
103+
};
104+
}
105+
return null;
106+
};
107+
}
108+
109+
// Custom 0nly numeric validator for form validation
110+
public onlyNumberValidator(fieldName: string = '') {
111+
return (control: FormControl) => {
112+
const name = control.value;
113+
const regex = /^[0-9]*$/;
114+
if (name && !regex.test(name)) {
115+
return {
116+
onlyNumber: 'Please enter a valid ' + fieldName + '. Only numbers are allowed.'
117+
};
118+
}
119+
return null;
120+
};
121+
}
122+
28123
}

src/assets/scss/_variable.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ $box-shadow-black: 5px 0px 5px #0000002e;
3939
$menu-icon-color: #000;
4040
$menu-icon-size: 30px;
4141
$active: #9786ff;
42-
$header-text: #6a5acd;
42+
$header-text: #6a5acd;
43+
44+
/* Heights */
45+
$home-height: calc(100vh - 60px);
46+
$content-height: calc(100vh - 100px);

src/styles.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ ol {
110110
.home {
111111
width: 100%;
112112
display: inline-flex;
113-
max-height: calc(100vh - 60px);
114-
min-height: calc(100vh - 60px);
113+
max-height: $home-height;
114+
min-height: $home-height;
115115
/* Side bar navigation element */
116116
.sidebar-nav{
117117
list-style: none;
@@ -176,7 +176,7 @@ ol {
176176
}
177177
.home-content {
178178
width: 100%;
179-
height: calc(100vh - 60px);
179+
height: $home-height;
180180
}
181181
}
182182

0 commit comments

Comments
 (0)