diff --git a/showcase/package-lock.json b/showcase/package-lock.json
index ab910b067b..27af40c2c4 100644
--- a/showcase/package-lock.json
+++ b/showcase/package-lock.json
@@ -949,15 +949,6 @@
"@babel/types": "^7.13.12"
}
},
- "@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.12.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz",
- "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.12.1"
- }
- },
"@babel/helper-split-export-declaration": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz",
@@ -1028,6 +1019,17 @@
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/helper-skip-transparent-expression-wrappers": "^7.12.1",
"@babel/plugin-proposal-optional-chaining": "^7.13.12"
+ },
+ "dependencies": {
+ "@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz",
+ "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.12.1"
+ }
+ }
}
},
"@babel/plugin-proposal-async-generator-functions": {
@@ -1071,16 +1073,6 @@
"@babel/plugin-syntax-dynamic-import": "^7.8.3"
}
},
- "@babel/plugin-proposal-export-namespace-from": {
- "version": "7.12.13",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.13.tgz",
- "integrity": "sha512-INAgtFo4OnLN3Y/j0VwAgw3HDXcDtX+C/erMvWzuV9v71r7urb6iyMXu7eM9IgLr1ElLlOkaHjJ0SbCmdOQ3Iw==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
- }
- },
"@babel/plugin-proposal-json-strings": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.13.8.tgz",
@@ -1091,16 +1083,6 @@
"@babel/plugin-syntax-json-strings": "^7.8.3"
}
},
- "@babel/plugin-proposal-logical-assignment-operators": {
- "version": "7.13.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.13.8.tgz",
- "integrity": "sha512-aul6znYB4N4HGweImqKn59Su9RS8lbUIqxtXTOcAGtNIDczoEFv+l1EhmX8rUBp3G1jMjKJm8m0jXVp63ZpS4A==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
- }
- },
"@babel/plugin-proposal-nullish-coalescing-operator": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz",
@@ -1153,6 +1135,17 @@
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/helper-skip-transparent-expression-wrappers": "^7.12.1",
"@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ },
+ "dependencies": {
+ "@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz",
+ "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.12.1"
+ }
+ }
}
},
"@babel/plugin-proposal-private-methods": {
@@ -1577,6 +1570,17 @@
"requires": {
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/helper-skip-transparent-expression-wrappers": "^7.12.1"
+ },
+ "dependencies": {
+ "@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz",
+ "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.12.1"
+ }
+ }
}
},
"@babel/plugin-transform-sticky-regex": {
@@ -1704,6 +1708,28 @@
"babel-plugin-polyfill-regenerator": "^0.2.0",
"core-js-compat": "^3.9.0",
"semver": "^6.3.0"
+ },
+ "dependencies": {
+ "@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.13.tgz",
+ "integrity": "sha512-INAgtFo4OnLN3Y/j0VwAgw3HDXcDtX+C/erMvWzuV9v71r7urb6iyMXu7eM9IgLr1ElLlOkaHjJ0SbCmdOQ3Iw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.12.13",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.13.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.13.8.tgz",
+ "integrity": "sha512-aul6znYB4N4HGweImqKn59Su9RS8lbUIqxtXTOcAGtNIDczoEFv+l1EhmX8rUBp3G1jMjKJm8m0jXVp63ZpS4A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.13.0",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ }
+ }
}
},
"@babel/preset-modules": {
@@ -1986,9 +2012,17 @@
"resolved": "https://registry.npmjs.org/@nationalbankbelgium/code-style/-/code-style-1.5.0.tgz",
"integrity": "sha512-I2c4/j/jbE0/RkCQ0cbT2b1UF/SqVlENNSCvmIi0afpIURmaFyIu1o6w+nEbS+SugcBtCsidfxllRqGtza0KNA=="
},
+ "@nationalbankbelgium/ngx-form-errors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@nationalbankbelgium/ngx-form-errors/-/ngx-form-errors-1.0.0.tgz",
+ "integrity": "sha512-14eiHMfRlr6fQk/D6Azb59EDMWR/4qHHPApfKih/U9MmTScRCWNzpN54A8jRbMYQX0MvxCHOhMkk31jM3y095g==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
"@nationalbankbelgium/stark-build": {
- "version": "file:../dist/packages-dist/stark-build/nationalbankbelgium-stark-build-10.2.0-4c6c9a6d.tgz",
- "integrity": "sha512-LOb6l7FTrWW0Fule3FiyXGYz7c2w8IVfo8gczur+xqxpXLh+8ERpGdONsC0n+dk36Vz/FyEhg0cFfIRDs9T3dw==",
+ "version": "file:../dist/packages-dist/stark-build/nationalbankbelgium-stark-build-10.2.0-092ad9c6.tgz",
+ "integrity": "sha512-hWWsGU+ac3LTZhnskOgJ/TRb6fbxCjCq9guAFestFx2X8qH+qkCZVMXpWNk9tumYJLvskiaKt3LU1UZRIUNNqg==",
"dev": true,
"requires": {
"@angular-builders/custom-webpack": "^8.3.0",
@@ -2013,8 +2047,8 @@
}
},
"@nationalbankbelgium/stark-core": {
- "version": "file:../dist/packages-dist/stark-core/nationalbankbelgium-stark-core-10.2.0-4c6c9a6d.tgz",
- "integrity": "sha512-uL3//JiGKvNnNWK1vF4CI8LsfOBVELw9Vd9X8IXDvOkuA3Dgj+pEv6n82QezZkLECtT+I5edAJVCaF6imSNptw==",
+ "version": "file:../dist/packages-dist/stark-core/nationalbankbelgium-stark-core-10.2.0-092ad9c6.tgz",
+ "integrity": "sha512-sMXaFILMlxCntLdOH5WKgHkq4/djG0nGALV96iCIfcYjJxOlMcETCZSlmRZeaKNNDrPKP6vyPohbVza7FuT51Q==",
"requires": {
"@angularclass/hmr": "^3.0.0",
"@ng-idle/core": "^8.0.0-beta.4",
@@ -2046,8 +2080,8 @@
}
},
"@nationalbankbelgium/stark-rbac": {
- "version": "file:../dist/packages-dist/stark-rbac/nationalbankbelgium-stark-rbac-10.2.0-4c6c9a6d.tgz",
- "integrity": "sha512-ZUcWz3v0m+v+YPXBY6RdOlUzcoDv4HxLArgmG+8lbbZgXrad2hx6zvpXKjwpeer/7OZQTj/xfEiZYxnvXJ0xCA==",
+ "version": "file:../dist/packages-dist/stark-rbac/nationalbankbelgium-stark-rbac-10.2.0-092ad9c6.tgz",
+ "integrity": "sha512-xewbqrtGWLqaN3kaO+yZjTx3e/+GMctgeU72D9z0JsP76fDOBXIirirtWG8Y/Puk+Bynx0+AjoQl3seg91xF+w==",
"requires": {
"@types/lodash-es": "^4.17.1",
"tslib": "^1.9.0"
@@ -2061,8 +2095,8 @@
}
},
"@nationalbankbelgium/stark-testing": {
- "version": "file:../dist/packages-dist/stark-testing/nationalbankbelgium-stark-testing-10.2.0-4c6c9a6d.tgz",
- "integrity": "sha512-IGiEzqGs4Ngx2QR2g108WkH7cD9JNGZi67CN0QSCjo34zXuDYlhJyw47R495huO6VWRsyNANJw++u0RUd+RkeA==",
+ "version": "file:../dist/packages-dist/stark-testing/nationalbankbelgium-stark-testing-10.2.0-092ad9c6.tgz",
+ "integrity": "sha512-Ibp+kM8wuHs8Kscy04x+etyYBrzA2TzzQwxa8UwTOEtzGKr5a6NUr2VXS0Z+TGoiIjPlqcx6BQxGAM+qV1nRQw==",
"dev": true,
"requires": {
"@angular-devkit/build-angular": ">= 0.800.0 < 0.900.0",
@@ -2087,8 +2121,8 @@
}
},
"@nationalbankbelgium/stark-ui": {
- "version": "file:../dist/packages-dist/stark-ui/nationalbankbelgium-stark-ui-10.2.0-4c6c9a6d.tgz",
- "integrity": "sha512-nHc77NL4kMFbJ5i5hBwf4os4uNsxHdZsoJvyWN41/+GOHWyPHfDto9rgiFhEGbvFuiw8hv+c+5DxWNS4JJ1dEQ==",
+ "version": "file:../dist/packages-dist/stark-ui/nationalbankbelgium-stark-ui-10.2.0-092ad9c6.tgz",
+ "integrity": "sha512-uczZlPjnHPsew8fvBSIt5T2NbIzAvdB2/hhaR0F/lNA74TauyuiK+BunpbWbNjPZZqUiKGcaviWrizFvVMLZnQ==",
"requires": {
"@angular/material-moment-adapter": "^8.2.0",
"@mdi/angular-material": "^4.0.96",
@@ -15859,8 +15893,7 @@
"tslib": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
- "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
- "dev": true
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
},
"tslint": {
"version": "5.20.1",
diff --git a/showcase/package.json b/showcase/package.json
index fe73c3baa0..c37f980a36 100644
--- a/showcase/package.json
+++ b/showcase/package.json
@@ -120,9 +120,10 @@
"@angular/platform-server": "^8.2.0",
"@angular/router": "^8.2.0",
"@nationalbankbelgium/code-style": "^1.5.0",
- "@nationalbankbelgium/stark-core": "file:../dist/packages-dist/stark-core/nationalbankbelgium-stark-core-10.2.0-4c6c9a6d.tgz",
- "@nationalbankbelgium/stark-rbac": "file:../dist/packages-dist/stark-rbac/nationalbankbelgium-stark-rbac-10.2.0-4c6c9a6d.tgz",
- "@nationalbankbelgium/stark-ui": "file:../dist/packages-dist/stark-ui/nationalbankbelgium-stark-ui-10.2.0-4c6c9a6d.tgz",
+ "@nationalbankbelgium/ngx-form-errors": "^1.0.0",
+ "@nationalbankbelgium/stark-core": "file:../dist/packages-dist/stark-core/nationalbankbelgium-stark-core-10.2.0-092ad9c6.tgz",
+ "@nationalbankbelgium/stark-rbac": "file:../dist/packages-dist/stark-rbac/nationalbankbelgium-stark-rbac-10.2.0-092ad9c6.tgz",
+ "@nationalbankbelgium/stark-ui": "file:../dist/packages-dist/stark-ui/nationalbankbelgium-stark-ui-10.2.0-092ad9c6.tgz",
"@uirouter/visualizer": "~7.2.1",
"angular-in-memory-web-api": "~0.9.0",
"basscss": "~8.1.0",
@@ -138,8 +139,8 @@
},
"devDependencies": {
"@compodoc/compodoc": "~1.1.11",
- "@nationalbankbelgium/stark-build": "file:../dist/packages-dist/stark-build/nationalbankbelgium-stark-build-10.2.0-4c6c9a6d.tgz",
- "@nationalbankbelgium/stark-testing": "file:../dist/packages-dist/stark-testing/nationalbankbelgium-stark-testing-10.2.0-4c6c9a6d.tgz",
+ "@nationalbankbelgium/stark-build": "file:../dist/packages-dist/stark-build/nationalbankbelgium-stark-build-10.2.0-092ad9c6.tgz",
+ "@nationalbankbelgium/stark-testing": "file:../dist/packages-dist/stark-testing/nationalbankbelgium-stark-testing-10.2.0-092ad9c6.tgz",
"@types/core-js": "~2.5.4",
"@types/hammerjs": "~2.0.39",
"@types/node": "~10.17.56",
diff --git a/showcase/src/app/app-menu.config.ts b/showcase/src/app/app-menu.config.ts
index d827e2ec4c..0506d70ee6 100644
--- a/showcase/src/app/app-menu.config.ts
+++ b/showcase/src/app/app-menu.config.ts
@@ -26,6 +26,13 @@ export const APP_MENU_CONFIG: StarkMenuConfig = {
isVisible: true,
isEnabled: true,
targetState: "news"
+ },
+ {
+ id: "reactive-form-errors",
+ label: "SHOWCASE.NGX_FORM_ERRORS.TITLE",
+ isVisible: true,
+ isEnabled: true,
+ targetState: "reactive-form-errors"
}
]
},
diff --git a/showcase/src/app/welcome/pages/index.ts b/showcase/src/app/welcome/pages/index.ts
index 92141ec039..5d600592cf 100644
--- a/showcase/src/app/welcome/pages/index.ts
+++ b/showcase/src/app/welcome/pages/index.ts
@@ -2,3 +2,4 @@ export * from "./getting-started";
export * from "./home";
export * from "./news";
export * from "./no-content";
+export * from "./reactive-form-errors";
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.html b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.html
new file mode 100644
index 0000000000..42620e9a7a
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.scss b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.scss
new file mode 100644
index 0000000000..e61ec8f140
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.scss
@@ -0,0 +1,5 @@
+:host mat-card {
+ box-sizing: border-box;
+ width: 100%;
+ min-height: 100%;
+}
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.ts b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.ts
new file mode 100644
index 0000000000..23dbfa5e32
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.component.ts
@@ -0,0 +1,46 @@
+import { Component, HostBinding, Input } from "@angular/core";
+
+type Colors = "primary" | "accent" | "warning" | "success";
+
+@Component({
+ selector: "app-card",
+ templateUrl: "./card.component.html",
+ styleUrls: ["./card.component.scss"]
+})
+export class CardComponent {
+ @HostBinding("class.app-card")
+ public cssClass = true;
+ @HostBinding("class.app-color-primary")
+ public primaryColor!: boolean;
+ @HostBinding("class.app-color-accent")
+ public accentColor!: boolean;
+ @HostBinding("class.app-color-warning")
+ public warningColor!: boolean;
+ @HostBinding("class.app-color-success")
+ public successColor!: boolean;
+
+ @Input()
+ public set color(color: Colors) {
+ this.primaryColor = false;
+ this.accentColor = false;
+ this.warningColor = false;
+ this.successColor = false;
+
+ switch (color) {
+ case "primary":
+ this.primaryColor = true;
+ break;
+ case "accent":
+ this.accentColor = true;
+ break;
+ case "warning":
+ this.warningColor = true;
+ break;
+ case "success":
+ this.successColor = true;
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.theme.scss b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.theme.scss
new file mode 100644
index 0000000000..d4e3871de0
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/card.theme.scss
@@ -0,0 +1,20 @@
+.app-card.app-color-primary mat-card {
+ background-color: mat-color($primary-palette, 500);
+ color: mat-contrast($primary-palette, 500);
+}
+
+.app-card.app-color-accent mat-card {
+ background-color: mat-color($primary-palette, 500);
+ color: mat-contrast($primary-palette, 500);
+}
+
+.app-card.app-color-warning mat-card {
+ background-color: mat-color($warning-palette, 500);
+ color: mat-contrast($warning-palette, 500);
+}
+
+.app-card.app-color-success mat-card {
+ /*Themes do not have a success map by default*/
+ background-color: mat-color($success-palette, 500);
+ color: mat-contrast($success-palette, 500);
+}
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/card/index.ts b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/index.ts
new file mode 100644
index 0000000000..8151bac4c8
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/card/index.ts
@@ -0,0 +1 @@
+export * from "./card.component";
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/index.ts b/showcase/src/app/welcome/pages/reactive-form-errors/components/index.ts
new file mode 100644
index 0000000000..a81d5c6e8a
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/index.ts
@@ -0,0 +1,2 @@
+export * from "./card";
+export * from "./translated-form-error";
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/index.ts b/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/index.ts
new file mode 100644
index 0000000000..4fad8db434
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/index.ts
@@ -0,0 +1 @@
+export * from "./translated-form-error.component";
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/translated-form-error.component.html b/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/translated-form-error.component.html
new file mode 100644
index 0000000000..22e7aaf61f
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/translated-form-error.component.html
@@ -0,0 +1 @@
+
{{ error.message | translate: error.params }}
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/translated-form-error.component.ts b/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/translated-form-error.component.ts
new file mode 100644
index 0000000000..c441df4199
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/components/translated-form-error/translated-form-error.component.ts
@@ -0,0 +1,47 @@
+import { Component, HostBinding, OnInit } from "@angular/core";
+import { LangChangeEvent, TranslateService } from "@ngx-translate/core";
+import { Observable } from "rxjs";
+import { NgxFormErrorComponent, NgxFormFieldError } from "@nationalbankbelgium/ngx-form-errors";
+
+@Component({
+ selector: "app-translated-form-error",
+ templateUrl: "./translated-form-error.component.html"
+})
+export class TranslatedFormErrorComponent implements NgxFormErrorComponent, OnInit {
+ @HostBinding("class")
+ public cssClass = "translated-form-error";
+
+ public errors: NgxFormFieldError[] = [];
+ public errors$!: Observable;
+ public fieldName!: string;
+
+ public constructor(public translateService: TranslateService) {}
+
+ public ngOnInit(): void {
+ this.translateService.onLangChange.subscribe((_ev: LangChangeEvent) => {
+ this.updateTranslateFieldName(this.translateService.instant(this.fieldName));
+ });
+ }
+
+ public subscribeToErrors(): void {
+ this.errors$.subscribe((errors: NgxFormFieldError[]) => {
+ this.errors = errors;
+
+ if (errors.length) {
+ // the formField can be retrieved from the "fieldName" param of any of the errors
+ this.fieldName = errors[0].params.fieldName;
+ this.updateTranslateFieldName(this.translateService.instant(this.fieldName));
+ }
+ });
+ }
+
+ public updateTranslateFieldName(translatedFieldName: string): void {
+ for (const error of this.errors) {
+ error.params = { ...error.params, fieldName: translatedFieldName };
+ }
+ }
+
+ public trackError(index: number): number {
+ return index;
+ }
+}
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/index.ts b/showcase/src/app/welcome/pages/reactive-form-errors/index.ts
new file mode 100644
index 0000000000..e2c99e3f05
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/index.ts
@@ -0,0 +1 @@
+export * from "./reactive-form-errors-page.component";
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/password-validator.ts b/showcase/src/app/welcome/pages/reactive-form-errors/password-validator.ts
new file mode 100644
index 0000000000..a87ca4f312
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/password-validator.ts
@@ -0,0 +1,31 @@
+import { FormControl, FormGroup, ValidationErrors, ValidatorFn } from "@angular/forms";
+
+export class PasswordValidator {
+ // Inspired on: http://plnkr.co/edit/Zcbg2T3tOxYmhxs7vaAm?p=preview
+ public static areEqual(formGroup: FormGroup): ValidationErrors | null {
+ let value: string | undefined;
+ let valid = true;
+
+ for (const key in formGroup.controls) {
+ if (formGroup.controls.hasOwnProperty(key)) {
+ const control: FormControl = formGroup.controls[key];
+
+ if (value === undefined) {
+ value = control.value;
+ } else if (value !== control.value) {
+ valid = false;
+ break;
+ }
+ }
+ }
+
+ /* tslint:disable-next-line:no-null-keyword */
+ return valid ? null : { areEqual: true };
+ }
+}
+
+export function getConfirmPasswordValidator(formGroup: FormGroup): ValidatorFn {
+ return (): ValidationErrors | null => {
+ return PasswordValidator.areEqual(formGroup);
+ };
+}
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.html b/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.html
new file mode 100644
index 0000000000..dfc04fc54b
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.html
@@ -0,0 +1,230 @@
+
+
+ SHOWCASE.NGX_FORM_ERRORS.TITLE
+
+
SHOWCASE.DEMO.SHARED.EXAMPLE_VIEWER_LIST
+
+
+
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.scss b/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.scss
new file mode 100644
index 0000000000..f2c59487b0
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.scss
@@ -0,0 +1,68 @@
+@import "~@nationalbankbelgium/stark-ui/assets/styles/media-queries";
+
+button {
+ margin: 8px;
+}
+
+.form-card {
+ mat-form-field {
+ box-sizing: border-box;
+ width: 100%;
+ @media #{$desktop-screen-query} {
+ width: 45%;
+ &:last-child {
+ margin-left: 10%;
+ }
+ }
+ }
+
+ mat-card-actions {
+ display: flex;
+ align-items: flex-start;
+ flex-wrap: wrap;
+ margin: -10px;
+
+ button {
+ margin: 10px;
+ @media #{$mobile-only-query} {
+ width: 100%;
+ }
+ }
+ }
+}
+
+.form-field-info {
+ @media #{$desktop-query} {
+ max-width: 33%;
+ }
+
+ max-width: 100%;
+
+ mat-card-content {
+ margin: 0;
+ padding: 5px 0;
+
+ pre {
+ overflow: auto;
+ box-sizing: border-box;
+ display: block;
+ max-height: 200px;
+
+ margin: inherit;
+ padding: 15px 5px;
+ border-radius: 4px;
+
+ background-color: rgba(0, 0, 0, 0.2);
+
+ word-break: break-all;
+ white-space: pre-wrap;
+
+ /* Non standard for webkit */
+
+ hyphens: auto;
+ &:empty {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.theme.scss b/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.theme.scss
new file mode 100644
index 0000000000..f73a5db4a1
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.theme.scss
@@ -0,0 +1,19 @@
+.app-card mat-form-field.maximum-height {
+ .mat-form-field-wrapper {
+ padding-bottom: 40px;
+
+ .mat-form-field-underline {
+ bottom: 40px;
+ }
+
+ .mat-form-field-subscript-wrapper {
+ top: calc(100% - 40px);
+ }
+ }
+}
+
+.validation-summary {
+ .translated-form-error div::before {
+ content: "• ";
+ }
+}
diff --git a/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.ts b/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.ts
new file mode 100644
index 0000000000..89b1b64c6b
--- /dev/null
+++ b/showcase/src/app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.ts
@@ -0,0 +1,74 @@
+import { Component, Inject } from "@angular/core";
+import { AbstractControl, FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { STARK_LOGGING_SERVICE, StarkLoggingService } from "@nationalbankbelgium/stark-core";
+import { getConfirmPasswordValidator } from "./password-validator";
+import { ReferenceLink } from "../../../shared/components/reference-block";
+
+@Component({
+ selector: "reactive-forms",
+ templateUrl: "./reactive-form-errors-page.component.html",
+ styleUrls: ["./reactive-form-errors-page.component.scss"]
+})
+export class ReactiveFormErrorsPageComponent {
+ public collapsed: boolean[] = [false, false, true];
+
+ public referenceList: ReferenceLink[] = [
+ {
+ label: "NGX Form errors library",
+ url: "https://github.com/NationalBankBelgium/ngx-form-errors"
+ }
+ ];
+
+ public formGroup: FormGroup;
+ public passwordPattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$";
+ public showValidationDetails = false;
+ public showValidationSummary = true;
+
+ public constructor(private formBuilder: FormBuilder, @Inject(STARK_LOGGING_SERVICE) public logger: StarkLoggingService) {
+ this.formGroup = this.formBuilder.group({
+ username: [undefined, Validators.required],
+ matchingPasswords: this.formBuilder.group({
+ password: [
+ "",
+ Validators.compose([
+ Validators.minLength(3),
+ Validators.maxLength(10),
+ Validators.required,
+ // this is for the letters (both uppercase and lowercase) and numbers validation
+ Validators.pattern(this.passwordPattern)
+ ])
+ ],
+ confirmPassword: [""] // validators for this field to be set afterwards (see below)
+ })
+ });
+
+ // setting the validator for confirmPassword field once we have created the form group
+ const confirmPasswordControl = this.formGroup.get("matchingPasswords.confirmPassword");
+ // we need to set the confirmPasswordValidator passing the "matchingPasswords" form group so that the errors of the form group are actually
+ // linked to the "confirmPassword" control because the NgxFormErrors directive is linked to the control and not to the form group!
+ confirmPasswordControl.setValidators([
+ Validators.required,
+ getConfirmPasswordValidator(this.formGroup.get("matchingPasswords"))
+ ]);
+ }
+
+ public getErrorClass(formControlName: string): string {
+ const formCtrl = this.formGroup.get(formControlName) as AbstractControl;
+ return formCtrl.errors && Object.keys(formCtrl.errors).length > 1 ? "maximum-height" : "small-height";
+ }
+
+ public toggleCollapsible(nb: number): void {
+ this.collapsed[nb] = !this.collapsed[nb];
+ }
+ public toggleValidationDetails(): void {
+ this.showValidationDetails = !this.showValidationDetails;
+ }
+
+ public toggleValidationSummary(): void {
+ this.showValidationSummary = !this.showValidationSummary;
+ }
+
+ public onSubmitUserDetails(formGroup: FormGroup): void {
+ this.logger.info("Submitted form:", formGroup.value);
+ }
+}
diff --git a/showcase/src/app/welcome/routes.ts b/showcase/src/app/welcome/routes.ts
index 6ea7383b2a..a27c90de0b 100644
--- a/showcase/src/app/welcome/routes.ts
+++ b/showcase/src/app/welcome/routes.ts
@@ -1,5 +1,11 @@
import { Ng2StateDeclaration } from "@uirouter/angular";
-import { GettingStartedPageComponent, HomePageComponent, NewsPageComponent, NoContentPageComponent } from "./pages";
+import {
+ GettingStartedPageComponent,
+ HomePageComponent,
+ NewsPageComponent,
+ NoContentPageComponent,
+ ReactiveFormErrorsPageComponent
+} from "./pages";
export const NEWS_STATES: Ng2StateDeclaration[] = [
{
@@ -29,6 +35,15 @@ export const NEWS_STATES: Ng2StateDeclaration[] = [
views: { "@": { component: NewsPageComponent } },
parent: "app"
},
+ {
+ name: "reactive-form-errors",
+ url: "^/reactive-form-errors", // use ^ to avoid double slash "//" in the URL after the domain (https://github.com/angular-ui/ui-router/wiki/URL-Routing#absolute-routes-)
+ data: {
+ translationKey: "SHOWCASE.NGX_FORM_ERRORS.TITLE"
+ },
+ views: { "@": { component: ReactiveFormErrorsPageComponent } },
+ parent: "app"
+ },
{
name: "otherwise",
url: "^/otherwise", // use ^ to avoid double slash "//" in the URL after the domain (https://github.com/angular-ui/ui-router/wiki/URL-Routing#absolute-routes-)
diff --git a/showcase/src/app/welcome/welcome.module.ts b/showcase/src/app/welcome/welcome.module.ts
index b7774496ec..b888bcc88e 100644
--- a/showcase/src/app/welcome/welcome.module.ts
+++ b/showcase/src/app/welcome/welcome.module.ts
@@ -1,8 +1,19 @@
import { NgModule } from "@angular/core";
import { UIRouterModule } from "@uirouter/angular";
-import { GettingStartedPageComponent, HomePageComponent, NewsPageComponent, NoContentPageComponent } from "./pages";
-import { NewsItemComponent } from "./components";
+import { MatDividerModule } from "@angular/material/divider";
+import { MatFormFieldModule } from "@angular/material/form-field";
+import { MatInputModule } from "@angular/material/input";
+import { NgxFormErrorsModule, NgxFormErrorsMessageService } from "@nationalbankbelgium/ngx-form-errors";
import { SharedModule } from "../shared";
+import {
+ GettingStartedPageComponent,
+ HomePageComponent,
+ NewsPageComponent,
+ NoContentPageComponent,
+ ReactiveFormErrorsPageComponent
+} from "./pages";
+import {CardComponent, TranslatedFormErrorComponent} from "./pages/reactive-form-errors/components";
+import { NewsItemComponent } from "./components";
import { NEWS_STATES } from "./routes";
@NgModule({
@@ -10,9 +21,48 @@ import { NEWS_STATES } from "./routes";
UIRouterModule.forChild({
states: NEWS_STATES
}),
- SharedModule
+ SharedModule,
+ MatDividerModule,
+ MatInputModule,
+ MatFormFieldModule,
+ NgxFormErrorsModule.forRoot({ formErrorComponent: TranslatedFormErrorComponent })
+ ],
+ declarations: [
+ GettingStartedPageComponent,
+ HomePageComponent,
+ NoContentPageComponent,
+ NewsPageComponent,
+ NewsItemComponent,
+ ReactiveFormErrorsPageComponent,
+ TranslatedFormErrorComponent,
+ CardComponent
],
- declarations: [GettingStartedPageComponent, HomePageComponent, NoContentPageComponent, NewsPageComponent, NewsItemComponent],
- exports: [GettingStartedPageComponent, HomePageComponent, NoContentPageComponent, NewsPageComponent, NewsItemComponent]
+ exports: [
+ GettingStartedPageComponent,
+ HomePageComponent,
+ NoContentPageComponent,
+ NewsPageComponent,
+ NewsItemComponent,
+ ReactiveFormErrorsPageComponent
+ ],
+ entryComponents: [TranslatedFormErrorComponent]
})
-export class WelcomeModule {}
+export class WelcomeModule {
+ /* tslint:disable:no-hardcoded-credentials */
+ public constructor(private errorMessageService: NgxFormErrorsMessageService) {
+ this.errorMessageService.addErrorMessages({
+ required: "SHOWCASE.NGX_FORM_ERRORS.FORM.VALIDATION.REQUIRED",
+ "matchingPasswords.password.required": "SHOWCASE.NGX_FORM_ERRORS.FORM.VALIDATION.PASSWORD_REQUIRED",
+ minlength: "SHOWCASE.NGX_FORM_ERRORS.FORM.VALIDATION.PASSWORD.MIN_LENGTH",
+ maxlength: "SHOWCASE.NGX_FORM_ERRORS.FORM.VALIDATION.PASSWORD.MAX_LENGTH",
+ pattern: "SHOWCASE.NGX_FORM_ERRORS.FORM.VALIDATION.PASSWORD.PATTERN",
+ areEqual: "SHOWCASE.NGX_FORM_ERRORS.FORM.VALIDATION.CONFIRM_PASSWORD.ARE_EQUAL"
+ });
+
+ this.errorMessageService.addFieldNames({
+ username: "SHOWCASE.NGX_FORM_ERRORS.FIELDS.ALIAS.USER_NAME",
+ "matchingPasswords.password": "not used, the alias defined via the directive takes precedence over this",
+ "matchingPasswords.confirmPassword": "SHOWCASE.NGX_FORM_ERRORS.FIELDS.ALIAS.CONFIRM_PASSWORD"
+ });
+ }
+}
diff --git a/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.html b/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.html
new file mode 100644
index 0000000000..29ac3de932
--- /dev/null
+++ b/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.html
@@ -0,0 +1,139 @@
+
diff --git a/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.scss b/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.scss
new file mode 100644
index 0000000000..f2c59487b0
--- /dev/null
+++ b/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.scss
@@ -0,0 +1,68 @@
+@import "~@nationalbankbelgium/stark-ui/assets/styles/media-queries";
+
+button {
+ margin: 8px;
+}
+
+.form-card {
+ mat-form-field {
+ box-sizing: border-box;
+ width: 100%;
+ @media #{$desktop-screen-query} {
+ width: 45%;
+ &:last-child {
+ margin-left: 10%;
+ }
+ }
+ }
+
+ mat-card-actions {
+ display: flex;
+ align-items: flex-start;
+ flex-wrap: wrap;
+ margin: -10px;
+
+ button {
+ margin: 10px;
+ @media #{$mobile-only-query} {
+ width: 100%;
+ }
+ }
+ }
+}
+
+.form-field-info {
+ @media #{$desktop-query} {
+ max-width: 33%;
+ }
+
+ max-width: 100%;
+
+ mat-card-content {
+ margin: 0;
+ padding: 5px 0;
+
+ pre {
+ overflow: auto;
+ box-sizing: border-box;
+ display: block;
+ max-height: 200px;
+
+ margin: inherit;
+ padding: 15px 5px;
+ border-radius: 4px;
+
+ background-color: rgba(0, 0, 0, 0.2);
+
+ word-break: break-all;
+ white-space: pre-wrap;
+
+ /* Non standard for webkit */
+
+ hyphens: auto;
+ &:empty {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.ts b/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.ts
new file mode 100644
index 0000000000..a89fabed04
--- /dev/null
+++ b/showcase/src/assets/examples/reactive-form-errors/reactive-form-errors.ts
@@ -0,0 +1,66 @@
+import { Component, Inject } from "@angular/core";
+import { AbstractControl, FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { STARK_LOGGING_SERVICE, StarkLoggingService } from "@nationalbankbelgium/stark-core";
+import { getConfirmPasswordValidator } from "./password-validator";
+
+@Component({
+ selector: "reactive-form-errors",
+ templateUrl: "./reactive-form-errors.html",
+ styleUrls: ["./reactive-form-errors.scss"]
+})
+export class ReactiveFormErrors {
+ public collapsed: boolean[] = [false, false, true];
+
+ public formGroup: FormGroup;
+ public passwordPattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$";
+ public showValidationDetails = false;
+ public showValidationSummary = true;
+
+ public constructor(private formBuilder: FormBuilder, @Inject(STARK_LOGGING_SERVICE) public logger: StarkLoggingService) {
+ this.formGroup = this.formBuilder.group({
+ username: [undefined, Validators.required],
+ matchingPasswords: this.formBuilder.group({
+ password: [
+ "",
+ Validators.compose([
+ Validators.minLength(3),
+ Validators.maxLength(10),
+ Validators.required,
+ // this is for the letters (both uppercase and lowercase) and numbers validation
+ Validators.pattern(this.passwordPattern)
+ ])
+ ],
+ confirmPassword: [""] // validators for this field to be set afterwards (see below)
+ })
+ });
+
+ // setting the validator for confirmPassword field once we have created the form group
+ const confirmPasswordControl = this.formGroup.get("matchingPasswords.confirmPassword");
+ // we need to set the confirmPasswordValidator passing the "matchingPasswords" form group so that the errors of the form group are actually
+ // linked to the "confirmPassword" control because the NgxFormErrors directive is linked to the control and not to the form group!
+ confirmPasswordControl.setValidators([
+ Validators.required,
+ getConfirmPasswordValidator(this.formGroup.get("matchingPasswords"))
+ ]);
+ }
+
+ public getErrorClass(formControlName: string): string {
+ const formCtrl = this.formGroup.get(formControlName) as AbstractControl;
+ return formCtrl.errors && Object.keys(formCtrl.errors).length > 1 ? "maximum-height" : "small-height";
+ }
+
+ public toggleCollapsible(nb: number): void {
+ this.collapsed[nb] = !this.collapsed[nb];
+ }
+ public toggleValidationDetails(): void {
+ this.showValidationDetails = !this.showValidationDetails;
+ }
+
+ public toggleValidationSummary(): void {
+ this.showValidationSummary = !this.showValidationSummary;
+ }
+
+ public onSubmitUserDetails(formGroup: FormGroup): void {
+ this.logger.info("Submitted form:", formGroup.value);
+ }
+}
diff --git a/showcase/src/assets/translations/en.json b/showcase/src/assets/translations/en.json
index f79504ad46..3d56f46f52 100644
--- a/showcase/src/assets/translations/en.json
+++ b/showcase/src/assets/translations/en.json
@@ -432,6 +432,49 @@
"NEWS": {
"TITLE": "News"
},
+ "NGX_FORM_ERRORS": {
+ "TITLE": "Reactive Forms errors",
+ "EXAMPLE": "Example",
+ "FORM": {
+ "VALIDATION": {
+ "REQUIRED": "{{fieldName}} is required",
+ "PASSWORD_REQUIRED": "{{fieldName}} must be provided",
+ "USER_NAME": {
+ "UNIQUE": "This username has already been taken"
+ },
+ "PASSWORD": {
+ "MAX_LENGTH": "Password cannot be more than {{requiredLength}} characters long",
+ "MIN_LENGTH": "Password must be at least {{requiredLength}} characters long",
+ "PATTERN": "Password must contain at least one uppercase, one lowercase and one number"
+ },
+ "CONFIRM_PASSWORD": {
+ "ARE_EQUAL": "Password mismatch"
+ }
+ },
+ "HIDE_DETAILS": "Hide validation details",
+ "SHOW_DETAILS": "Show validation details",
+ "HIDE_SUMMARY": "Hide validation summary",
+ "SHOW_SUMMARY": "Show validation summary",
+ "SUBMIT": "Submit"
+ },
+ "FIELDS": {
+ "USER_NAME": "User Name",
+ "PASSWORD": "Password",
+ "CONFIRM_PASSWORD": "Confirm password",
+ "ALIAS": {
+ "USER_NAME": "Your username",
+ "PASSWORD_ALIAS": "A valid password",
+ "CONFIRM_PASSWORD": "Password confirmation"
+ },
+ "INFO": {
+ "HAS_ERRORS": "Has errors: {{hasErrors}}",
+ "HAS_SPECIFIC_ERROR": "Has '{{error}}' error: {{hasError}}",
+ "ERROR": "'{{error}}' error:",
+ "ERRORS": "Errors:",
+ "IS_TOUCHED": "Is touched: {{isTouched}}"
+ }
+ }
+ },
"OTHERWISE": {
"TITLE": "Otherwise"
},
diff --git a/showcase/src/assets/translations/fr.json b/showcase/src/assets/translations/fr.json
index 4e384d6688..0641ba36f6 100644
--- a/showcase/src/assets/translations/fr.json
+++ b/showcase/src/assets/translations/fr.json
@@ -432,6 +432,49 @@
"NEWS": {
"TITLE": "Nouvelles"
},
+ "NGX_FORM_ERRORS": {
+ "TITLE": "Reactive Forms errors",
+ "EXAMPLE": "Exemple",
+ "FORM": {
+ "VALIDATION": {
+ "REQUIRED": "Le champ \"{{fieldName}}\" est requis",
+ "PASSWORD_REQUIRED": "Le champ \"{{fieldName}}\" est requis",
+ "USER_NAME": {
+ "UNIQUE": "Ce nom d'utilisateur est déjà pris"
+ },
+ "PASSWORD": {
+ "MAX_LENGTH": "Le mot de passe ne peut pas contenir plus de {{requiredLength}} caractères",
+ "MIN_LENGTH": "Le mot de passe doit contenir au moins {{requiredLength}} caractères",
+ "PATTERN": "Le mot de passe doit contenir au moins une majuscule, une minuscule et un chiffre."
+ },
+ "CONFIRM_PASSWORD": {
+ "ARE_EQUAL": "Les mots de passe ne correspondent pas"
+ }
+ },
+ "HIDE_DETAILS": "Masquer les détails de validation",
+ "SHOW_DETAILS": "Afficher les détails de validation",
+ "HIDE_SUMMARY": "Masquer le résumé de validation",
+ "SHOW_SUMMARY": "Afficher le résumé de validation",
+ "SUBMIT": "Soumettre"
+ },
+ "FIELDS": {
+ "USER_NAME": "Nom d'utilisateur",
+ "PASSWORD": "Mot de passe",
+ "CONFIRM_PASSWORD": "Confirmez le mot de passe",
+ "ALIAS": {
+ "USER_NAME": "Votre nom d'utilisateur",
+ "PASSWORD_ALIAS": "Un mot de passe valide",
+ "CONFIRM_PASSWORD": "Confirmation du mot de passe"
+ },
+ "INFO": {
+ "HAS_ERRORS": "Contient des erreurs: {{hasErrors}}",
+ "HAS_SPECIFIC_ERROR": "Contient l'erreur '{{error}}': {{hasError}}",
+ "ERROR": "Erreur '{{error}}':",
+ "ERRORS": "Erreurs:",
+ "IS_TOUCHED": "Est touché: {{isTouched}}"
+ }
+ }
+ },
"OTHERWISE": {
"TITLE": "Autre"
},
diff --git a/showcase/src/assets/translations/nl.json b/showcase/src/assets/translations/nl.json
index 5bcee9df46..739bf9688b 100644
--- a/showcase/src/assets/translations/nl.json
+++ b/showcase/src/assets/translations/nl.json
@@ -432,6 +432,49 @@
"NEWS": {
"TITLE": "Nieuws"
},
+ "NGX_FORM_ERRORS": {
+ "TITLE": "Reactive Forms errors",
+ "EXAMPLE": "Voorbeeld",
+ "FORM": {
+ "VALIDATION": {
+ "REQUIRED": "{{fieldName}} is verplicht",
+ "PASSWORD_REQUIRED": "{{fieldName}} moet worden gegeven",
+ "USER_NAME": {
+ "UNIQUE": "Deze gebruikersnaam is al in gebruik"
+ },
+ "PASSWORD": {
+ "MAX_LENGTH": "Wachtwoord mag niet meer dan {{requiredLength}} tekens lang zijn",
+ "MIN_LENGTH": "Wachtwoord moet minimaal {{requiredLength}} tekens lang zijn",
+ "PATTERN": "Wwachtwoord moet minimaal één hoofdletter, één kleine letter en één cijfer bevatten"
+ },
+ "CONFIRM_PASSWORD": {
+ "ARE_EQUAL": "Wachtwoord komt niet overeen"
+ }
+ },
+ "HIDE_DETAILS": "Validatiedetails verbergen",
+ "SHOW_DETAILS": "Validatiedetails weergeven",
+ "HIDE_SUMMARY": "Validatieoverzicht verbergen",
+ "SHOW_SUMMARY": "Validatieoverzicht tonen",
+ "SUBMIT": "Indienen"
+ },
+ "FIELDS": {
+ "USER_NAME": "Gebruikersnaam",
+ "PASSWORD": "Wachtwoord",
+ "CONFIRM_PASSWORD": "Bevestig wachtwoord",
+ "ALIAS": {
+ "USER_NAME": "Uw gebruikersnaam",
+ "PASSWORD_ALIAS": "Een geldig wachtwoord",
+ "CONFIRM_PASSWORD": "Wachtwoordbevestiging"
+ },
+ "INFO": {
+ "HAS_ERRORS": "Veld heeft fouten: {{hasErrors}}",
+ "HAS_SPECIFIC_ERROR": "Veld heeft de '{{error}}' fout: {{hasError}}",
+ "ERROR": "'{{error}}' fout:",
+ "ERRORS": "Fouten:",
+ "IS_TOUCHED": "Veld is aangeraakt: {{isTouched}}"
+ }
+ }
+ },
"OTHERWISE": {
"TITLE": "Andersom"
},
diff --git a/showcase/src/styles/_theme.scss b/showcase/src/styles/_theme.scss
index 34ac649730..a700eff430 100644
--- a/showcase/src/styles/_theme.scss
+++ b/showcase/src/styles/_theme.scss
@@ -16,3 +16,5 @@ Import the local variables file first to set the correct variables, see:
@import "../app/demo-ui/pages/route-search/demo-route-search-page.component-theme";
@import "../app/demo-ui/components/table-regular/table-regular-theme";
@import "../app/styleguide/pages/layout/styleguide-layout-page.theme";
+@import "../app/welcome/pages/reactive-form-errors/components/card/card.theme";
+@import "../app/welcome/pages/reactive-form-errors/reactive-form-errors-page.component.theme";