Skip to content
This repository was archived by the owner on Aug 7, 2020. It is now read-only.

Commit f26267c

Browse files
JDownloadertremblaymath
authored andcommitted
feat(field): add custom error message and ng-pattern support (#109)
feat(oui-field): add custom error message and ng-pattern support
1 parent 290e96e commit f26267c

File tree

6 files changed

+168
-17
lines changed

6 files changed

+168
-17
lines changed

packages/oui-field/README.md

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@
3030
name="email"
3131
ng-model="$ctrl.user.email">
3232
</oui-field>
33+
34+
<oui-field label="{{'Username'}}"
35+
error-messages="{pattern: 'Username must be alphabetic with a length between 3 and 8.'}">
36+
<input
37+
class="oui-input"
38+
type="text"
39+
id="username"
40+
name="username"
41+
ng-model="$ctrl.user.username"
42+
ng-pattern="/^[a-zA-Z]{3,8}$/">
43+
</oui-field>
3344
```
3445

3546
### Checkbox
@@ -147,9 +158,20 @@
147158

148159
## API
149160

150-
### oui-datagrid
151-
152-
| Attribute | Type | Binding | One-time binding | Values | Default | Description |
153-
| ---- | ---- | ---- | ---- | ---- | ---- | ---- |
154-
| `help-text` | string | @? | yes | | | the field label |
155-
| `label` | function | @? | yes | | | a text to help fill the form field |
161+
| Attribute | Type | Binding | One-time binding | Values | Default | Description |
162+
| ---- | ---- | ---- | ---- | ---- | ---- | ---- |
163+
| `error-messages` | object | <? | no | | | a dictionary to override default messages |
164+
| `help-text` | string | @? | yes | | | the field label |
165+
| `label` | function | @? | yes | | | a text to help fill the form field |
166+
167+
`error-messages` object can override error messages for validation.
168+
169+
| Attribute | Type | Default |
170+
| ---- | ---- | ---- |
171+
| `required` | string | Mandatory. |
172+
| `email` | string | Invalid email. |
173+
| `min` | string | Too low (1 min). |
174+
| `max` | string | Too high (100 max). |
175+
| `minlength` | string | Too short (6 characters min). |
176+
| `maxlength` | string | Too high (12 characters max). |
177+
| `pattern` | string | Invalid format. |

packages/oui-field/src/field.component.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import template from "./field.html";
44
export default {
55
bindings: {
66
label: "@?",
7-
helpText: "@?"
7+
helpText: "@?",
8+
errorMessages: "<?"
89
},
910
controller,
1011
require: {

packages/oui-field/src/field.controller.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ const VALIDATION_PARAMETERS = {
2222
min: ["min", "ng-min"],
2323
max: ["max", "ng-max"],
2424
minlength: ["minlength", "ng-minlength"],
25-
maxlength: ["maxlength", "ng-maxlength"]
25+
maxlength: ["maxlength", "ng-maxlength"],
26+
pattern: ["pattern", "ng-pattern"]
2627
};
2728

2829
export default class FieldController {
@@ -124,7 +125,7 @@ export default class FieldController {
124125

125126
showErrors (controlElement, name) {
126127
this.$timeout(() => {
127-
if (this.form[name].$invalid) {
128+
if (this.form[name] && this.form[name].$invalid) {
128129
angular.element(controlElement).addClass(FieldController.getErrorClass(controlElement));
129130
this.$ouiFieldElement.addClass("oui-field_error");
130131
this.isErrorVisible = true;
@@ -149,16 +150,20 @@ export default class FieldController {
149150
getFirstError () {
150151
const names = Object.keys(this.controls);
151152
for (let i = 0; i < names.length; ++i) {
152-
if (this.form[names[i]].$invalid) {
153+
if (this.form[names[i]] && this.form[names[i]].$invalid) {
153154
return this.form[names[i]].$error;
154155
}
155156
}
156157

157158
return null;
158159
}
159160

161+
getMessageString (errorName) {
162+
return (this.errorMessages && this.errorMessages[errorName]) || this.ouiFieldConfiguration.translations.errors[errorName];
163+
}
164+
160165
getErrorMessage (errorName) {
161-
const message = this.ouiFieldConfiguration.translations.errors[errorName];
166+
const message = this.getMessageString(errorName);
162167
const parameterValue = this.validationParameters[this.currentErrorField][errorName];
163168
return message.replace(`{{${errorName}}}`, parameterValue);
164169
}

packages/oui-field/src/field.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
ng-bind="$ctrl.getErrorMessage('min')"></span>
2323
<span ng-message="max"
2424
ng-bind="$ctrl.getErrorMessage('max')"></span>
25+
<span ng-message="pattern"
26+
ng-bind="$ctrl.getErrorMessage('pattern')"></span>
2527
</span>
2628
</div>
2729
<div class="oui-field__helper"

packages/oui-field/src/field.provider.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export default class {
77
min: "Too low ({{min}} min).",
88
max: "Too high ({{max}} max).",
99
minlength: "Too short ({{minlength}} characters min).",
10-
maxlength: "Too high ({{maxlength}} characters max)."
10+
maxlength: "Too high ({{maxlength}} characters max).",
11+
pattern: "Invalid format."
1112
}
1213
};
1314
}

packages/oui-field/src/index.spec.js

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ describe("ouiField", () => {
6969
expect(getLabel(element)).toBeNull();
7070
});
7171

72-
it("should set the for attribute on label", () => {
72+
it("should set the 'for' attribute on label", () => {
7373
const id = "lastname";
7474

7575
const element = TestUtils.compileTemplate(`
@@ -90,6 +90,60 @@ describe("ouiField", () => {
9090
expect(getLabel(element).getAttribute("for")).toEqual(id);
9191
});
9292

93+
it("should trigger error when invalid format", () => {
94+
95+
const element = TestUtils.compileTemplate(`
96+
<form name="form">
97+
<oui-field label="{{'username'}}">
98+
<input type="text"
99+
class="oui-input"
100+
type="text"
101+
id="username"
102+
name="username"
103+
ng-model="$ctrl.username"
104+
ng-pattern="/^[a-zA-Z]{3,8}$/">
105+
</oui-field>
106+
</form>
107+
`);
108+
const controller = getField(element).controller("ouiField");
109+
110+
$timeout.flush();
111+
112+
const $control = getControl(controller, "username");
113+
$control.val("ch@t12");
114+
$control.triggerHandler("input");
115+
$control.triggerHandler("blur");
116+
117+
expect(controller.getFirstError().pattern).toBeTruthy();
118+
});
119+
120+
it("should trigger error when length too short", () => {
121+
122+
const element = TestUtils.compileTemplate(`
123+
<form name="form">
124+
<oui-field label="{{'username'}}">
125+
<input type="text"
126+
class="oui-input"
127+
type="text"
128+
id="username"
129+
name="username"
130+
minlength="6"
131+
ng-model="$ctrl.username">
132+
</oui-field>
133+
</form>
134+
`);
135+
const controller = getField(element).controller("ouiField");
136+
137+
$timeout.flush();
138+
139+
const $control = getControl(controller, "username");
140+
$control.val("abc");
141+
$control.triggerHandler("input");
142+
$control.triggerHandler("blur");
143+
144+
expect(controller.getFirstError().minlength).toBeTruthy();
145+
});
146+
93147
it("should set the name of the form field in the controller", () => {
94148
const name = "lastname";
95149

@@ -128,16 +182,16 @@ describe("ouiField", () => {
128182
id="age"
129183
name="age"
130184
ng-model="$ctrl.user.age"
131-
min="{{$ctrl.validation.min}}"
132-
max="{{$ctrl.validation.max}}">
185+
ng-min="{{$ctrl.validation.min}}"
186+
ng-max="{{$ctrl.validation.max}}">
133187
<input
134188
class="oui-input"
135189
type="text"
136190
id="name"
137191
name="name"
138192
ng-model="$ctrl.user.name"
139-
minlength="{{$ctrl.validation.minlength}}"
140-
maxlength="{{$ctrl.validation.maxlength}}">
193+
ng-minlength="{{$ctrl.validation.minlength}}"
194+
ng-maxlength="{{$ctrl.validation.maxlength}}">
141195
</oui-field>
142196
`, {
143197
validation
@@ -466,6 +520,72 @@ describe("ouiField", () => {
466520
});
467521
});
468522

523+
describe("with validation", () => {
524+
it("should retrieve custom error messages", () => {
525+
const message = "Username must be a least 6 characters.";
526+
527+
const element = TestUtils.compileTemplate(`
528+
<form name="form">
529+
<oui-field label="{{'username'}}"
530+
error-messages="{minlength: '${message}'}">
531+
<input type="text"
532+
class="oui-input"
533+
type="text"
534+
id="username"
535+
name="username"
536+
ng-minlength="6"
537+
ng-model="$ctrl.username">
538+
</oui-field>
539+
</form>
540+
`);
541+
542+
const controller = getField(element).controller("ouiField");
543+
544+
$timeout.flush();
545+
546+
const $control = getControl(controller, "username");
547+
$control.val("abc");
548+
$control.triggerHandler("input");
549+
$control.triggerHandler("blur");
550+
551+
$timeout.flush();
552+
553+
expect(controller.getFirstError().minlength).toBeTruthy();
554+
expect(controller.getErrorMessage("minlength")).toBe(message);
555+
});
556+
557+
it("should give a message containing parameters", () => {
558+
const messageMinlength = 5;
559+
560+
const element = TestUtils.compileTemplate(`
561+
<form name="form">
562+
<oui-field label="{{'username'}}">
563+
<input type="text"
564+
class="oui-input"
565+
type="text"
566+
id="username"
567+
name="username"
568+
ng-minlength="${messageMinlength}"
569+
ng-model="$ctrl.username">
570+
</oui-field>
571+
</form>
572+
`);
573+
574+
const controller = getField(element).controller("ouiField");
575+
576+
$timeout.flush();
577+
578+
const $control = getControl(controller, "username");
579+
$control.val("abc");
580+
$control.triggerHandler("input");
581+
$control.triggerHandler("blur");
582+
583+
$timeout.flush();
584+
585+
expect(controller.getFirstError().minlength).toBeTruthy();
586+
expect(controller.getErrorMessage("minlength")).toContain(messageMinlength);
587+
});
588+
});
469589
});
470590

471591
});

0 commit comments

Comments
 (0)