Skip to content

Commit 936c33e

Browse files
authored
Feature/ng10 (#11)
feature(npm-updates\angular-10\form-validator): upgrade for node & angular packages, upgrade to angular 10, and fix for form-validator to allow deep properties
1 parent 1b0f5b3 commit 936c33e

15 files changed

+3818
-2528
lines changed

angular-src/angular.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
"main": "src/main.ts",
2020
"polyfills": "src/polyfills.ts",
2121
"tsConfig": "src/tsconfig.app.json",
22+
"allowedCommonJsDependencies": [
23+
"validator"
24+
],
2225
"assets": [
2326
"src/favicon.ico",
2427
"src/assets"

angular-src/e2e/tsconfig.e2e.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"extends": "../tsconfig.json",
2+
"extends": "../tsconfig.base.json",
33
"compilerOptions": {
44
"outDir": "../out-tsc/app",
55
"module": "commonjs",

angular-src/package-lock.json

Lines changed: 3181 additions & 2237 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

angular-src/package.json

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,26 @@
1515
"dev:ssr": "ng run angular-src:serve-ssr",
1616
"serve:ssr": "node dist/server/main.js",
1717
"build:ssr": "ng build --prod && ng run angular-src:server:production",
18-
"prerender": "ng run angular-src:prerender"
18+
"prerender": "ng run angular-src:prerender",
19+
"postinstall": "./node_modules/.bin/ngcc --tsconfig=src/tsconfig.app.json"
1920
},
2021
"private": true,
2122
"dependencies": {
22-
"@angular/animations": "^9.1.11",
23-
"@angular/common": "^9.1.11",
24-
"@angular/compiler": "^9.1.11",
25-
"@angular/core": "^9.1.11",
26-
"@angular/forms": "^9.1.11",
27-
"@angular/http": "^7.2.16",
28-
"@angular/platform-browser": "^9.1.11",
29-
"@angular/platform-browser-dynamic": "^9.1.11",
30-
"@angular/platform-server": "^9.1.11",
31-
"@angular/router": "^9.1.11",
32-
"@fortawesome/fontawesome-free": "^5.13.1",
23+
"@angular/animations": "^10.0.8",
24+
"@angular/common": "^10.0.8",
25+
"@angular/compiler": "^10.0.8",
26+
"@angular/core": "^10.0.8",
27+
"@angular/forms": "^10.0.8",
28+
"@angular/platform-browser": "^10.0.8",
29+
"@angular/platform-browser-dynamic": "^10.0.8",
30+
"@angular/platform-server": "^10.0.8",
31+
"@angular/router": "^10.0.8",
32+
"@fortawesome/fontawesome-free": "^5.14.0",
3333
"@ng-toolkit/universal": "^8.1.0",
3434
"@nguniversal/express-engine": "^9.1.1",
3535
"@ngx-loading-bar/core": "^4.2.0",
3636
"angularx-social-login": "^2.3.1",
37-
"bootstrap": "^4.5.0",
37+
"bootstrap": "^4.5.2",
3838
"bootstrap-social": "^5.1.1",
3939
"class-transformer": "^0.2.3",
4040
"class-transformer-validator": "^0.8.0",
@@ -47,39 +47,39 @@
4747
"ngx-toastr": "^11.3.3",
4848
"popper.js": "^1.16.1",
4949
"roboto-fontface": "^0.10.0",
50-
"rxjs": "^6.5.5",
50+
"rxjs": "^6.6.2",
5151
"tether": "^1.4.7",
5252
"ts-loader": "6.2.1",
53-
"tslib": "^1.13.0",
53+
"tslib": "^2.0.0",
5454
"zone.js": "~0.10.3"
5555
},
5656
"devDependencies": {
57-
"@angular-devkit/build-angular": "^0.901.9",
58-
"@angular/cli": "^9.1.9",
59-
"@angular/compiler-cli": "^9.1.11",
60-
"@angular/language-service": "^9.1.11",
57+
"@angular-devkit/build-angular": "^0.1000.5",
58+
"@angular/cli": "^10.0.5",
59+
"@angular/compiler-cli": "^10.0.8",
60+
"@angular/language-service": "^10.0.8",
6161
"@nguniversal/builders": "^9.1.1",
62-
"@types/express": "^4.17.6",
62+
"@types/express": "^4.17.7",
6363
"@types/faker": "^4.1.12",
64-
"@types/jasmine": "^3.5.10",
64+
"@types/jasmine": "^3.5.12",
6565
"@types/jasminewd2": "~2.0.8",
66-
"@types/node": "^13.13.12",
67-
"codelyzer": "^5.2.2",
66+
"@types/node": "^13.13.15",
67+
"codelyzer": "^6.0.0",
6868
"faker": "^4.1.0",
6969
"jasmine-core": "~3.5.0",
70-
"jasmine-spec-reporter": "~4.2.1",
71-
"karma": "~4.4.1",
70+
"jasmine-spec-reporter": "~5.0.0",
71+
"karma": "~5.0.0",
7272
"karma-chrome-launcher": "~3.1.0",
73-
"karma-coverage-istanbul-reporter": "~2.1.1",
74-
"karma-jasmine": "^3.1.1",
75-
"karma-jasmine-html-reporter": "^1.5.4",
73+
"karma-coverage-istanbul-reporter": "~3.0.2",
74+
"karma-jasmine": "~3.3.0",
75+
"karma-jasmine-html-reporter": "^1.5.0",
7676
"karma-junit-reporter": "^2.0.1",
7777
"karma-mocha-reporter": "^2.2.5",
7878
"node-sass": "^4.14.1",
79-
"protractor": "^5.4.4",
79+
"protractor": "~7.0.0",
8080
"ts-node": "~8.6.2",
81-
"tslint": "~6.0.0",
82-
"typescript": "~3.7.5",
81+
"tslint": "~6.1.0",
82+
"typescript": "~3.9.7",
8383
"webpack-cli": "^3.3.12"
8484
}
8585
}
File renamed without changes.

angular-src/src/app/shared/directives/form-validator.directive.ts

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { validate, ValidationError } from 'class-validator';
22

33
import {
4-
AfterViewInit, Directive, ElementRef, EventEmitter, Input, OnChanges, Output, SimpleChanges
4+
AfterViewInit, Directive, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, Output,
5+
SimpleChanges
56
} from '@angular/core';
67

78
/**
@@ -11,13 +12,7 @@ import {
1112
@Directive({
1213
selector: '[appFormValidator]',
1314
})
14-
export class FormValidatorDirective implements AfterViewInit, OnChanges {
15-
/**
16-
* A class-validator implemented object, which is used to validate the fields in the form.
17-
*
18-
* @type {*}
19-
* @memberof FormValidatorDirective
20-
*/
15+
export class FormValidatorDirective implements AfterViewInit, OnChanges, OnDestroy {
2116
@Input() appFormValidator: any;
2217
/**
2318
*Hides all of the form validation errors text.
@@ -36,6 +31,32 @@ export class FormValidatorDirective implements AfterViewInit, OnChanges {
3631
return this._isFormValid;
3732
}
3833

34+
private getValidationErrorFromFieldName(
35+
name: string,
36+
validationErrors: ValidationError[]
37+
): ValidationError {
38+
let lastValidationError: ValidationError = null;
39+
40+
// We split using '-' which represents a deeper property
41+
const split = name.split('-');
42+
43+
while (true) {
44+
const property = split.shift();
45+
46+
if (lastValidationError)
47+
lastValidationError = lastValidationError.children.find((v) => v.property === property);
48+
else lastValidationError = validationErrors.find((v) => v.property === property);
49+
50+
// If no validation error was found, return null
51+
if (!lastValidationError) return;
52+
53+
// Update the last validation error
54+
55+
// If it's the end of the field name, return the validation error
56+
if (split.length === 0) return lastValidationError;
57+
}
58+
}
59+
3960
/**
4061
* Called each time the form is completely valid or invalid.
4162
*
@@ -59,6 +80,14 @@ export class FormValidatorDirective implements AfterViewInit, OnChanges {
5980
}
6081

6182
ngAfterViewInit(): void {
83+
this.attachEventListeners();
84+
this.updateForm();
85+
}
86+
87+
/**
88+
* Get all of the form group inputs, and listen to all of the input events.
89+
*/
90+
attachEventListeners() {
6291
// Get all of the form group inputs
6392
this.getFormGroupInputs().forEach((input: HTMLInputElement) => {
6493
// Detect when a value was changed in one of the fields
@@ -72,8 +101,23 @@ export class FormValidatorDirective implements AfterViewInit, OnChanges {
72101
input.parentElement.appendChild(div);
73102
} else next.classList.add('input-description-validation');
74103
});
104+
}
75105

76-
this.updateForm();
106+
/**
107+
* Removes all of the form group input listeners.
108+
*/
109+
detachEventListeners() {
110+
this.getFormGroupInputs().forEach((input: HTMLInputElement) => {
111+
input.removeEventListener('input', this.inputValueChangeEventFunc);
112+
});
113+
}
114+
115+
/**
116+
* Removes the attached event listeners, and re-attaches to them.
117+
*/
118+
reattachEventListeners() {
119+
this.detachEventListeners();
120+
this.attachEventListeners();
77121
}
78122

79123
ngOnChanges(changes: SimpleChanges): void {
@@ -117,22 +161,18 @@ export class FormValidatorDirective implements AfterViewInit, OnChanges {
117161
* Goes through all of the form and checks for any issues, updates all of the fields accordingly.
118162
*/
119163
updateForm(): Promise<boolean> {
120-
const prevIsFormValid = this._isFormValid;
164+
return validate(this.appFormValidator).then((validationErrors) => {
165+
const prevIsFormValid = this._isFormValid;
166+
this._isFormValid = true;
121167

122-
return validate(this.appFormValidator).then((results) => {
123-
let errorsFound = 0;
124168
this.getFormGroupInputs().forEach((input: HTMLInputElement) => {
125169
const name = input.name;
126-
const validationError = results.find((result) => result.property === name);
170+
const validationError = this.getValidationErrorFromFieldName(name, validationErrors);
127171
this.updateFormField(input, validationError);
128172

129-
if (validationError) errorsFound += 1;
173+
if (validationError) this._isFormValid = false;
130174
});
131175

132-
// Form is only valid if no errors were found
133-
this._isFormValid = errorsFound === 0;
134-
135-
// Check if the form validation state was changed
136176
if (prevIsFormValid !== this._isFormValid)
137177
this.appFormValidatorIsFormValidChange.emit(this._isFormValid);
138178

@@ -147,4 +187,8 @@ export class FormValidatorDirective implements AfterViewInit, OnChanges {
147187
const formElement = this.elementRef.nativeElement;
148188
return formElement.querySelectorAll('.form-group>input');
149189
}
190+
191+
ngOnDestroy(): void {
192+
this.detachEventListeners();
193+
}
150194
}

angular-src/src/tsconfig.app.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"extends": "../tsconfig.json",
2+
"extends": "../tsconfig.base.json",
33
"compilerOptions": {
44
"outDir": "../out-tsc/app",
55
"types": [],

angular-src/src/tsconfig.server.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
"extends": "./tsconfig.app.json",
33
"compilerOptions": {
44
"outDir": "../out-tsc/app",
5-
"module": "commonjs",
65
"types": [
76
"node"
8-
],
7+
], "target": "es2016"
8+
,
99
},
1010
"angularCompilerOptions": {
1111
"entryModule": "app/app.server.module#AppServerModule"

angular-src/src/tsconfig.spec.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"extends": "../tsconfig.json",
2+
"extends": "../tsconfig.base.json",
33
"compilerOptions": {
44
"outDir": "../out-tsc/spec",
55
"types": [

angular-src/tsconfig.base.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"compileOnSave": false,
3+
"compilerOptions": {
4+
"baseUrl": "./",
5+
"module": "es2020",
6+
"outDir": "./dist/out-tsc",
7+
"sourceMap": true,
8+
"declaration": false,
9+
"moduleResolution": "node",
10+
"emitDecoratorMetadata": true,
11+
"experimentalDecorators": true,
12+
"target": "es5",
13+
"typeRoots": [
14+
"node_modules/@types"
15+
],
16+
"lib": [
17+
"es2017",
18+
"dom"
19+
],
20+
"paths": {
21+
"@services": [
22+
"src/app/core/services/index.ts"
23+
],
24+
"@core/*": [
25+
"src/app/core/*"
26+
],
27+
"@shared/*": [
28+
"src/app/shared/*"
29+
]
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)