Skip to content

Commit 7f76d60

Browse files
committed
Merge pull request #13 from srsgores/master
Fix title not setting custom error messages; update documentation
2 parents d86f769 + 7bda094 commit 7f76d60

File tree

2 files changed

+95
-68
lines changed

2 files changed

+95
-68
lines changed

README.md

Lines changed: 89 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
# Ember CLI HTML5 Validation
22

3-
This Ember CLI addon aims to provide a simple form validation feature. It also includes a simple async button that
4-
is aims to be used with forms for better user experience.
3+
This Ember CLI addon provides a simple form validation feature, aligned with the HTML5 spec. It also includes a simple async ``button`` component that aims to be used with forms for better user experience.
54

6-
## Major limitations
5+
## Browser Support
76

8-
This addon is mostly targeted to simple forms (for now). But more importantly, it's only supported in browsers
9-
that support built-in form validation (IE10+, Firefox 4+, Chrome 10+, Safari 5+, Opera 10.1+). For older IE versions,
10-
you may use the [H5F polyfill](https://github.com/ryanseddon/H5F).
7+
This addon is mostly targeted to simple forms (for now). But more importantly, it's only supported in browsers that support built-in form validation (IE10+, Firefox 4+, Chrome 10+, Safari 5+, Opera 10.1+). For older IE versions, you may use the [H5F polyfill](https://github.com/ryanseddon/H5F).
118

129
## Installation
1310

@@ -17,7 +14,7 @@ Add the following line to your `package.json`:
1714
"ember-cli-html5-validation": "0.0.*",
1815
```
1916

20-
## Future work
17+
## Future Work
2118

2219
* Better integration with Ember Data
2320
* Being able to customize more easily templates
@@ -27,25 +24,23 @@ Add the following line to your `package.json`:
2724

2825
### Basics
2926

30-
This addon automatically adds validation feature to input, radio, checkbox and text areas, without any change. If
31-
you add the following code:
27+
This addon automatically adds validation to ``input``, ``radio``, ``checkbox``, and ``textarea`` form controls without any change. If you add the following code:
3228

3329
```html
34-
{{input required='required'}}
30+
{{input required=true}}
3531
```
3632

37-
It will automatically adds an error message if you focus out from the field with an empty value, or when you submit
38-
the form. All built-in HTML5 validation rules are supported. For instance:
33+
This addon will automatically add an error message when the user focuses out from the field with an empty value, or when the user submits the form. All built-in HTML5 validation rules are supported. For instance:
3934

4035
```html
4136
<!-- Make sure the input is required and is a valid email -->
42-
{{input type='email' value=email required='required'}}
37+
{{input type="email" value=email required=true}}
4338

4439
<!-- The password is required and must be at least 6 characters long -->
45-
{{input type='password' value=password pattern='.{6,}' required='required'}}
40+
{{input type="password" value=password pattern=".{6,}" required=true}}
4641

4742
<!-- Input length must be 20 maximum -->
48-
{{input value=firstName maxlength=20}}
43+
{{input value=firstName maxlength=20 required=true}}
4944
```
5045

5146
By default, this addon comes with predefined error messages for each error ([see here](https://github.com/maestrooo/ember-cli-html5-validation/blob/master/addon/mixins/validatable-input.js#L33),
@@ -73,13 +68,13 @@ ValidatableInput.reopen({
7368
});
7469
```
7570

76-
The browser messages have the advantage of being translated, please note however that each browser have their
77-
own messages, so you must not rely on those if you want the same messages in all browser.
71+
The browser messages have the advantage of being translated. Please note, however, that each browser have their own messages, so you must not rely on those if you want the same messages in all browser.
7872

79-
#### Custom messages
73+
**Note**: if you declare ``title`` attributes on your ``required`` input fields, their respective ``title`` values will be appended to the browser error messages.
8074

81-
You can use the "title" attribute on form to define a message that will be shown if validation fail. This is standard
82-
on the spec for "pattern" messages, but I decided to extend it to any validation. For instance:
75+
#### Custom Error Messages
76+
77+
The easiest way to customize your inputs' error messages is by adding the ``title``. Adding the ``title`` attribute on your form input controls will cause a message of the ``title``'s value to be shown if validation fail. This is standard on the spec for "pattern" messages, but this addon extends it to any validation. For instance:
8378

8479
```html
8580
<!-- This will show "You must accept agreements" if checkbox is not checked}}
@@ -88,99 +83,111 @@ on the spec for "pattern" messages, but I decided to extend it to any validation
8883
8984
### Validatable forms
9085
91-
While you can now have built-in validation for inputs, what we want is actually being able to prevent form submission,
92-
automatically scrolling to first field that fail...
86+
While you can now have built-in validation for inputs, what we want is actually to prevent form submission, automatically scrolling to first field that fails validation.
9387
9488
To do that, you must wrap your inputs around the `validatable-form` component:
9589
9690
```html
97-
{{#validatable-form action='save'}}
91+
{{#validatable-form action="save"}}
9892
<div class="form-control">
99-
{{input name='first-name' value=firstName required='required'}}
93+
<label for="first-name">First Name</label>
94+
{{input id="first-name" title="Please provide a first name" value=firstName required=true autofocus=true}}
10095
</div>
10196
10297
<div class="form-control">
103-
{{input name='last-name' value=lastName required='required'}}
98+
<label for="last-name">Last Name</label>
99+
{{input id="last-name" title="Please provide a last name" value=lastName required=true}}
104100
</div>
105101
106-
<input type="submit"}}
102+
<button type="submit" title="Verify account information, and continue to profile setup">Verify and Continue</button>
107103
{{/validatable-form}}
108104
```
109105
110-
If you submit the form, Ember CLI HTML5 Validation will automatically run validation on each field, showing the
111-
input error, and automatically scrolling to the first error. If error happen, no form submission will happen.
106+
When the user submits the form, Ember CLI HTML5 Validation will automatically run validation on each field, showing any input errors and automatically scrolling to the first error. **Form submission will be prevented if *any* errors are encountered**.
112107
113-
On the other hand, if validation passes, an action will be sent to the action defined in the `validatable-form`
114-
component.
108+
On the other hand, if validation passes, an action will be sent to the action defined in the `validatable-form` component.
115109
116110
### Using with Ember-Data
117111
118-
This addon offers native integration with Ember-Data. To do this, you only need to pass the `model` attribute to
119-
the validatable form:
112+
This addon offers native integration with Ember-Data. To do this, you only need to pass the `model` attribute to the validatable form:
120113
121114
```html
122-
{{#validatable-form action='save' model=model}}
115+
{{#validatable-form action="save" model=model}}
123116
<div class="form-control">
124-
{{input id='first-name' value=firstName required='required'}}
117+
<label for="first-name">First Name</label>
118+
{{input id="first-name" title="Please provide a first name" value=firstName required=true autofocus=true}}
125119
</div>
126120
127121
<div class="form-control">
128-
{{input id='last-name' value=lastName required='required'}}
122+
<label for="last-name">Last Name</label>
123+
{{input id="last-name" title="Please provide a last name" value=lastName required=true}}
129124
</div>
130125
131-
<input type="submit"}}
126+
<button type="submit" title="Verify account information, and continue to profile setup">Verify and Continue</button>
132127
{{/validatable-form}}
133128
```
134129
135-
This will provide two things:
130+
This will:
131+
132+
* Send the ``model`` along with the action (``save`` in this case)
133+
* Extract any *server-side* errors.
134+
135+
When client validation successfully passes, the assigned ``action`` is bubbled up. In case of errors that are returned by server, Ember CLI HTML5 Validation will automatically extract errors (assuming that errors hash is formatted properly) and will show them along corresponding fields.
136+
137+
Server-side errors, in the case of the ``RESTAdapter`` or ``ActiveModelAdapter`` will typically be in the form of a nested ``Array`` in the place of the field:
138+
139+
*Response from server with validation messages*
140+
141+
```json
142+
{
143+
"user": {
144+
"firstName": ["First name must be present"],
145+
"lastName": ["Last name must be present"]
146+
}
147+
}
148+
```
136149
137-
* The model will be send along the action.
138-
* It also extracts server-side errors.
150+
For more information on ``DS.Errors``, [please refer to the Ember documentation](http://emberjs.com/api/data/classes/DS.Errors.html); a working example [can be found here](http://jsfiddle.net/L96Mb/10/light/).
139151
140-
When client validation successfully passes, the action is submitted. In case of errors that are returned by server,
141-
Ember CLI HTML5 Validation will automatically extracts errors (assuming that errors hash is formatted properly) and
142-
will show them along corresponding fields.
152+
**Note**: on some Ember-Data adapters, you may need to configure creation of ``DS.InvalidError`` object on failure (this is done out of the box if you are using ActiveModel Adapter). Furthermore, you must add an "id" on each input, that is the dasherized version of the property. For instance, if your server returns the following payload:
143153
144-
For this to work, you must configure Ember-Data to properly creates a DS.InvalidError object on failure (this is done
145-
out of the box if you are using ActiveModel Adapter). Furthermore, you must add an "id" on each input, that is the
146-
dasherized version of the property. For instance, if your server returns the following payload:
154+
**Example of expected error response from ``ActiveModelAdapter``**
147155
148156
```json
149157
{
150-
"errors": {
151-
"first_name": [
152-
"Your First Name is not valid (lol)"
153-
]
158+
"user": {
159+
"errors": {
160+
"first_name": [
161+
"Your First Name is not valid (lol)"
162+
]
163+
}
164+
}
154165
}
155166
}
156167
```
157168
158-
Your input must have an id whose value is "first-name".
169+
In this case, the input must have an ``id`` whose value is "first-name".
159170
160-
> This is currently a bit hacky and I want to make this more efficient / allow to work on associations.
171+
> This is currently a bit "hacky" and we want to make this more efficient / allow to work on associations.
161172
162173
### Cookbook
163174
164175
#### Dependent field
165176
166-
If you have an input that is required only if a checkbox is checked, you can do that:
177+
If you have an input that is required only if a checkbox is checked, you can do this:
167178
168179
```html
169-
{{input name='first-name' value=firstName required=agreements}}
170-
{{input type='checkbox' name='agreements' checked=agreements}}
180+
{{input name="first-name" value=firstName required=agreements}}
181+
{{input type="checkbox" name="agreements" checked=agreements}}
171182
```
172183
173184
#### Custom logic
174185
175-
While this library is mostly aims to perform quick validations with minimal overhead, HTML5 allows you to provide
176-
custom logic and set custom message by calling the `setCustomValidity` method on your input. When you call this method,
177-
an `invalid` event will be triggered and the `ValidatableInput` will automatically show it.
186+
While this library serves mostly to perform quick validations with minimal overhead, HTML5 allows you to provide custom logic and to set custom messages by calling the `setCustomValidity` method on your input. When you call this method, an `invalid` event will be triggered, and the `ValidatableInput` will automatically show it.
178187
179188
### Async Button
180189
181-
Ember-CLI-HTML5-Validation now comes with a minimal async button. This component can be used for your forms to provide
182-
immediate feedback when the form is submitting, and then comes into an error or success state. Whenever it enters into
183-
error or success state, it will transition back to initial state after 1.5s.
190+
Ember-CLI-HTML5-Validation now comes with a minimal ``async`` button. This component can be used for your forms to provide immediate feedback when the form is submitting, and then comes into an ``error`` or ``success`` state. Whenever the form enters into an ``error`` or ``success`` state, this addon will transition the form back to its initial state after 1.5s.
184191
185192
Here are the classes added to the button depending on the status:
186193
@@ -192,7 +199,27 @@ You can override the default template by setting your own template for the `asyn
192199
an example usage:
193200
194201
```html
195-
{{async-button class='button' value='Sign Up' isLoading=isSaving isValid=isValid}}
202+
{{async-button class="button" value="Sign Up" isLoading=isSaving isValid=isValid}}
196203
```
197204
198-
`isLoading` and `isValid` property can comes either from computed properties or your models.
205+
And with a form:
206+
207+
```html
208+
{{#validatable-form action="save" model=model}}
209+
<div class="form-control">
210+
<label for="first-name">First Name</label>
211+
{{input id="first-name" title="Please provide a first name" value=firstName required=true autofocus=true}}
212+
</div>
213+
214+
<div class="form-control">
215+
<label for="last-name">Last Name</label>
216+
{{input id="last-name" title="Please provide a last name" value=lastName required=true}}
217+
</div>
218+
219+
{{async-button class="button" isLoading=isSaving isValid=isValid}}Sign Up{{/async-button}}
220+
{{/validatable-form}}
221+
```
222+
223+
The `isLoading` and `isValid` properties can either come from computed properties or from your models.
224+
225+
**Note**: the ``async-button`` component will automatically add the ``disabled`` attribute when ``isValid`` is false.

addon/mixins/validatable-input.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export default Ember.Mixin.create({
114114
*/
115115
validate: function() {
116116
var input = this.get('element'),
117-
jQueryElement = Ember.$(input);
117+
jQueryElement = Ember.$(input);
118118

119119
// According to spec, inputs that have "formnovalidate" should bypass any validation
120120
if (input.hasAttribute('formnovalidate')) {
@@ -156,16 +156,16 @@ export default Ember.Mixin.create({
156156
*/
157157
renderErrorMessage: function() {
158158
var element = this.$(),
159-
parent = element.parent(),
160-
errorMessage = this.get('errorMessage');
159+
parent = element.parent(),
160+
errorMessage = this.get('errorMessage');
161161

162162
if (null === errorMessage) {
163163
parent.removeClass('has-error');
164164
element.next('.input-error').remove();
165165
} else {
166166
parent.addClass('has-error');
167167
element.next('.input-error').remove();
168-
element.after('<p class="input-error" role="alert">' + errorMessage + '</p>');
168+
element.after(`<label class="input-error" role="alert" for="${element.attr("id")}">${errorMessage}</label>`);
169169
}
170170
}.observes('errorMessage'),
171171

@@ -184,13 +184,13 @@ export default Ember.Mixin.create({
184184
}
185185

186186
var errorTemplates = this.get('errorTemplates'),
187-
type = target.getAttribute('type');
187+
type = target.getAttribute('type');
188188

189189
// We first check for the "required" case
190190
if (target.validity.valueMissing) {
191191
// For checkbox, we allow to have a title attribute that is shown instead of the
192192
// required message. Very useful for things like "You must accept our terms"
193-
if (type === 'checkbox' && target.hasAttribute('title')) {
193+
if (target.hasAttribute('title')) {
194194
return target.getAttribute('title');
195195
}
196196

0 commit comments

Comments
 (0)