Skip to content

Commit

Permalink
Merge pull request #13 from srsgores/master
Browse files Browse the repository at this point in the history
Fix title not setting custom error messages; update documentation
  • Loading branch information
bakura10 committed Jun 22, 2015
2 parents d86f769 + 7bda094 commit 7f76d60
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 68 deletions.
151 changes: 89 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
# Ember CLI HTML5 Validation

This Ember CLI addon aims to provide a simple form validation feature. It also includes a simple async button that
is aims to be used with forms for better user experience.
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.

## Major limitations
## Browser Support

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).
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).

## Installation

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

## Future work
## Future Work

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

### Basics

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

```html
{{input required='required'}}
{{input required=true}}
```

It will automatically adds an error message if you focus out from the field with an empty value, or when you submit
the form. All built-in HTML5 validation rules are supported. For instance:
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:

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

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

<!-- Input length must be 20 maximum -->
{{input value=firstName maxlength=20}}
{{input value=firstName maxlength=20 required=true}}
```

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),
Expand Down Expand Up @@ -73,13 +68,13 @@ ValidatableInput.reopen({
});
```

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.
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.

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

You can use the "title" attribute on form to define a message that will be shown if validation fail. This is standard
on the spec for "pattern" messages, but I decided to extend it to any validation. For instance:
#### Custom Error Messages

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:

```html
<!-- This will show "You must accept agreements" if checkbox is not checked}}
Expand All @@ -88,99 +83,111 @@ on the spec for "pattern" messages, but I decided to extend it to any validation
### Validatable forms
While you can now have built-in validation for inputs, what we want is actually being able to prevent form submission,
automatically scrolling to first field that fail...
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.
To do that, you must wrap your inputs around the `validatable-form` component:
```html
{{#validatable-form action='save'}}
{{#validatable-form action="save"}}
<div class="form-control">
{{input name='first-name' value=firstName required='required'}}
<label for="first-name">First Name</label>
{{input id="first-name" title="Please provide a first name" value=firstName required=true autofocus=true}}
</div>
<div class="form-control">
{{input name='last-name' value=lastName required='required'}}
<label for="last-name">Last Name</label>
{{input id="last-name" title="Please provide a last name" value=lastName required=true}}
</div>
<input type="submit"}}
<button type="submit" title="Verify account information, and continue to profile setup">Verify and Continue</button>
{{/validatable-form}}
```
If you submit the form, Ember CLI HTML5 Validation will automatically run validation on each field, showing the
input error, and automatically scrolling to the first error. If error happen, no form submission will happen.
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**.
On the other hand, if validation passes, an action will be sent to the action defined in the `validatable-form`
component.
On the other hand, if validation passes, an action will be sent to the action defined in the `validatable-form` component.
### Using with Ember-Data
This addon offers native integration with Ember-Data. To do this, you only need to pass the `model` attribute to
the validatable form:
This addon offers native integration with Ember-Data. To do this, you only need to pass the `model` attribute to the validatable form:
```html
{{#validatable-form action='save' model=model}}
{{#validatable-form action="save" model=model}}
<div class="form-control">
{{input id='first-name' value=firstName required='required'}}
<label for="first-name">First Name</label>
{{input id="first-name" title="Please provide a first name" value=firstName required=true autofocus=true}}
</div>
<div class="form-control">
{{input id='last-name' value=lastName required='required'}}
<label for="last-name">Last Name</label>
{{input id="last-name" title="Please provide a last name" value=lastName required=true}}
</div>
<input type="submit"}}
<button type="submit" title="Verify account information, and continue to profile setup">Verify and Continue</button>
{{/validatable-form}}
```
This will provide two things:
This will:
* Send the ``model`` along with the action (``save`` in this case)
* Extract any *server-side* errors.
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.
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:
*Response from server with validation messages*
```json
{
"user": {
"firstName": ["First name must be present"],
"lastName": ["Last name must be present"]
}
}
```
* The model will be send along the action.
* It also extracts server-side errors.
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/).
When client validation successfully passes, the action is submitted. In case of errors that are returned by server,
Ember CLI HTML5 Validation will automatically extracts errors (assuming that errors hash is formatted properly) and
will show them along corresponding fields.
**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:
For this to work, you must configure Ember-Data to properly creates a 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:
**Example of expected error response from ``ActiveModelAdapter``**
```json
{
"errors": {
"first_name": [
"Your First Name is not valid (lol)"
]
"user": {
"errors": {
"first_name": [
"Your First Name is not valid (lol)"
]
}
}
}
}
```
Your input must have an id whose value is "first-name".
In this case, the input must have an ``id`` whose value is "first-name".
> This is currently a bit hacky and I want to make this more efficient / allow to work on associations.
> This is currently a bit "hacky" and we want to make this more efficient / allow to work on associations.
### Cookbook
#### Dependent field
If you have an input that is required only if a checkbox is checked, you can do that:
If you have an input that is required only if a checkbox is checked, you can do this:
```html
{{input name='first-name' value=firstName required=agreements}}
{{input type='checkbox' name='agreements' checked=agreements}}
{{input name="first-name" value=firstName required=agreements}}
{{input type="checkbox" name="agreements" checked=agreements}}
```
#### Custom logic
While this library is mostly aims to perform quick validations with minimal overhead, HTML5 allows you to provide
custom logic and set custom message 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.
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.
### Async Button
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 it enters into
error or success state, it will transition back to initial state after 1.5s.
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.
Here are the classes added to the button depending on the status:
Expand All @@ -192,7 +199,27 @@ You can override the default template by setting your own template for the `asyn
an example usage:
```html
{{async-button class='button' value='Sign Up' isLoading=isSaving isValid=isValid}}
{{async-button class="button" value="Sign Up" isLoading=isSaving isValid=isValid}}
```
`isLoading` and `isValid` property can comes either from computed properties or your models.
And with a form:
```html
{{#validatable-form action="save" model=model}}
<div class="form-control">
<label for="first-name">First Name</label>
{{input id="first-name" title="Please provide a first name" value=firstName required=true autofocus=true}}
</div>
<div class="form-control">
<label for="last-name">Last Name</label>
{{input id="last-name" title="Please provide a last name" value=lastName required=true}}
</div>
{{async-button class="button" isLoading=isSaving isValid=isValid}}Sign Up{{/async-button}}
{{/validatable-form}}
```
The `isLoading` and `isValid` properties can either come from computed properties or from your models.
**Note**: the ``async-button`` component will automatically add the ``disabled`` attribute when ``isValid`` is false.
12 changes: 6 additions & 6 deletions addon/mixins/validatable-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export default Ember.Mixin.create({
*/
validate: function() {
var input = this.get('element'),
jQueryElement = Ember.$(input);
jQueryElement = Ember.$(input);

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

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

Expand All @@ -184,13 +184,13 @@ export default Ember.Mixin.create({
}

var errorTemplates = this.get('errorTemplates'),
type = target.getAttribute('type');
type = target.getAttribute('type');

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

Expand Down

0 comments on commit 7f76d60

Please sign in to comment.