From 42ce5ddb2adeee49e3a050853270c06a9ad897dc Mon Sep 17 00:00:00 2001
From: Dan Monroe
Date: Fri, 4 Sep 2015 16:25:23 -0400
Subject: [PATCH 1/5] Added remaining input helper attributes as passthroughs
---
app/templates/components/paper-input.hbs | 29 +++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/app/templates/components/paper-input.hbs b/app/templates/components/paper-input.hbs
index 4cdf60988..37c727b28 100644
--- a/app/templates/components/paper-input.hbs
+++ b/app/templates/components/paper-input.hbs
@@ -9,7 +9,34 @@
{{#if textarea}}
{{textarea class="md-input" id=inputElementId placeholder=placeholder value=value focus-in="focusIn" key-down="keyDown" focus-out="focusOut" disabled=disabled required=required autofocus=autofocus}}
{{else}}
- {{input class="md-input" id=inputElementId placeholder=placeholder type=type value=value focus-in="focusIn" key-down="keyDown" focus-out="focusOut" disabled=disabled required=required autofocus=autofocus}}
+ {{input class="md-input" id=inputElementId placeholder=placeholder type=type value=value focus-in="focusIn" key-down="keyDown" focus-out="focusOut" disabled=disabled required=required autofocus=autofocus
+ accept=attr-accept
+ autocomplete=attr-autocomplete
+ autosave=attr-autosave
+ form=attr-form
+ formaction=attr-formaction
+ formenctype=attr-formenctype
+ formmethod=attr-formmethod
+ formnovalidate=attr-formnovalidate
+ formtarget=attr-formtarget
+ height=attr-height
+ inputmode=attr-inputmode
+ min=attr-min
+ maxlength=attr-maxlength
+ max=attr-max
+ multiple=attr-multiple
+ name=attr-name
+ pattern=attr-pattern
+ readonly=attr-readonly
+ selectionDirection=attr-selectionDirection
+ size=attr-size
+ spellcheck=attr-spellcheck
+ step=attr-step
+ tabindex=attr-tabindex
+ width=attr-width
+
+ enter=event-enter
+ }}
{{/if}}
{{#unless hideAllMessages}}
From af8a0bf34667aa4982e2701f61c2e81624dfa864 Mon Sep 17 00:00:00 2001
From: Dan Monroe
Date: Sun, 6 Sep 2015 23:36:35 -0400
Subject: [PATCH 2/5] Added integration tests for paper-input
---
.../components/paper-input-test.js | 285 ++++++++++++++++++
1 file changed, 285 insertions(+)
create mode 100644 tests/integration/components/paper-input-test.js
diff --git a/tests/integration/components/paper-input-test.js b/tests/integration/components/paper-input-test.js
new file mode 100644
index 000000000..b83218466
--- /dev/null
+++ b/tests/integration/components/paper-input-test.js
@@ -0,0 +1,285 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('paper-input', 'Integration | Component | paper input', {
+ integration: true
+});
+
+test('renders default theme on wrapper', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input}}`);
+
+ var actual = this.$('md-input-container').attr('class');
+ var expected = 'ember-view md-default-theme';
+ assert.equal(actual, expected);
+});
+
+test('renders with label', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input label="Name"}}`);
+
+ var actual = this.$('md-input-container label').text();
+ var expected = 'Name';
+ assert.equal(actual, expected);
+});
+
+test('renders with icon', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input icon="person" icon-class="name"}}`);
+
+ var actual = this.$('md-input-container md-icon').attr('class');
+ var expected = 'name ember-view paper-icon md-font material-icons md-default-theme person';
+ assert.equal(actual, expected);
+});
+
+test('renders input', function (assert) {
+ assert.expect(2);
+
+ this.render(hbs`{{paper-input icon="person" icon-class="name"}}`);
+
+ var actual = this.$('md-input-container input');
+ var expected = 'md-input ember-view ember-text-field';
+ assert.equal(actual.attr('class'), expected);
+ assert.equal(actual.attr('type'), 'text');
+});
+
+test('renders input with id', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input inputElementId="testId"}}`);
+
+ var actual = this.$('md-input-container input').attr('id');
+ var expected = 'testId';
+ assert.equal(actual, expected);
+});
+
+test('renders input with placeholder', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input placeholder="Enter value here"}}`);
+
+ var actual = this.$('md-input-container input').attr('placeholder');
+ var expected = 'Enter value here';
+ assert.equal(actual, expected);
+});
+
+test('renders input with value', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input value="current value"}}`);
+
+ var actual = this.$('md-input-container input').val();
+ var expected = 'current value';
+ assert.equal(actual, expected);
+});
+
+test('renders input as disabled', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input disabled=true}}`);
+
+ var actual = this.$('md-input-container input').attr('disabled');
+ var expected = 'disabled';
+ assert.equal(actual, expected);
+});
+
+test('renders input as required', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input required=true}}`);
+
+ var actual = this.$('md-input-container input').attr('required');
+ var expected = 'required';
+ assert.equal(actual, expected);
+});
+
+test('renders input as autofocus', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input autofocus=true}}`);
+
+ var actual = this.$('md-input-container input').attr('autofocus');
+ var expected = 'autofocus';
+ assert.equal(actual, expected);
+});
+
+test('renders input with accept types of files', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input attr-accept="audio/*|video/*|image/*"}}`);
+
+ var actual = this.$('md-input-container input').attr('accept');
+ var expected = 'audio/*|video/*|image/*';
+ assert.equal(actual, expected);
+});
+
+test('renders input with attribute autocomplete', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input attr-autocomplete=true}}`);
+
+ var actual = this.$('md-input-container input').attr('autocomplete');
+ var expected = 'true';
+
+ assert.equal(actual, expected);
+});
+
+test('renders input with attribute form', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input attr-form="myform"}}`);
+
+ var actual = this.$('md-input-container input').attr('form');
+ var expected = 'myform';
+
+ assert.equal(actual, expected);
+});
+
+test('renders input with attribute formnovalidate', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input attr-formnovalidate="formnovalidate"}}`);
+
+ var actual = this.$('md-input-container input').attr('formnovalidate');
+ var expected = 'formnovalidate';
+
+ assert.equal(actual, expected);
+});
+
+test('renders input with attribute formtarget', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input attr-formtarget="_blank"}}`);
+
+ var actual = this.$('md-input-container input').attr('formtarget');
+ var expected = '_blank';
+
+ assert.equal(actual, expected);
+});
+
+test('renders input with attribute formenctype', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input attr-formenctype="multipart/form-data"}}`);
+
+ var actual = this.$('md-input-container input').attr('formenctype');
+ var expected = 'multipart/form-data';
+
+ assert.equal(actual, expected);
+});
+
+test('renders input with multiple form attributes', function (assert) {
+ assert.expect(5);
+
+ this.render(hbs`{{paper-input type="submit" attr-form="myform" attr-formnovalidate="formnovalidate" attr-formtarget="_blank" attr-formenctype="multipart/form-data"}}`);
+
+ var $input = this.$('md-input-container input');
+
+ var actual = $input.attr('type');
+ var expected = 'submit';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('form');
+ expected = 'myform';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('formnovalidate');
+ expected = 'formnovalidate';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('formtarget');
+ expected = '_blank';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('formenctype');
+ expected = 'multipart/form-data';
+ assert.equal(actual, expected);
+
+});
+
+test('renders input with input mode attribute', function (assert) {
+ assert.expect(1);
+
+ this.render(hbs`{{paper-input attr-inputmode="numeric"}}`);
+
+ var $input = this.$('md-input-container input');
+
+ var actual = $input.attr('inputmode');
+ var expected = 'numeric';
+ assert.equal(actual, expected);
+});
+
+test('renders input with multiple attributes', function (assert) {
+ assert.expect(12);
+
+ this.render(hbs`{{paper-input type="submit"
+ attr-min="2"
+ attr-maxlength="20"
+ attr-max="42"
+ attr-multiple="true"
+ attr-name="elementname"
+ attr-pattern="(999)999-9999"
+ attr-readonly="true"
+ attr-size="30"
+ attr-spellcheck="true"
+ attr-step="2"
+ attr-tabindex="1138"
+ }}`);
+
+ var $input = this.$('md-input-container input');
+
+ var actual = $input.attr('type');
+ var expected = 'submit';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('min');
+ expected = '2';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('maxlength');
+ expected = '20';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('max');
+ expected = '42';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('multiple');
+ expected = 'multiple';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('name');
+ expected = 'elementname';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('pattern');
+ expected = '(999)999-9999';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('readonly');
+ expected = 'readonly';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('size');
+ expected = '30';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('spellcheck');
+ expected = 'true';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('step');
+ expected = '2';
+ assert.equal(actual, expected);
+
+ actual = $input.attr('tabindex');
+ expected = '1138';
+ assert.equal(actual, expected);
+
+});
+
+
+
From 3639fd37ed4520c3f0e9824df013c840d9f70916 Mon Sep 17 00:00:00 2001
From: Dan Monroe
Date: Mon, 7 Sep 2015 23:33:50 -0400
Subject: [PATCH 3/5] Added input helper attributes for textareas as well.
---
app/templates/components/paper-input.hbs | 17 ++++-
tests/dummy/app/templates/input.hbs | 83 +++++++++++++++++++++++-
2 files changed, 97 insertions(+), 3 deletions(-)
diff --git a/app/templates/components/paper-input.hbs b/app/templates/components/paper-input.hbs
index 37c727b28..f98bab8e6 100644
--- a/app/templates/components/paper-input.hbs
+++ b/app/templates/components/paper-input.hbs
@@ -7,7 +7,22 @@
{{/if}}
{{#if textarea}}
- {{textarea class="md-input" id=inputElementId placeholder=placeholder value=value focus-in="focusIn" key-down="keyDown" focus-out="focusOut" disabled=disabled required=required autofocus=autofocus}}
+ {{textarea class="md-input" id=inputElementId placeholder=placeholder value=value focus-in="focusIn" key-down="keyDown" focus-out="focusOut" disabled=disabled required=required autofocus=autofocus
+ name=attr-name
+ rows=attr-rows
+ cols=attr-cols
+ maxlength=attr-maxlength
+ tabindex=attr-tabindex
+ selectionEnd=attr-selectionEnd
+ selectionStart=attr-selectionStart
+ selectionDirection=attr-selectionDirection
+ wrap=attr-wrap
+ readonly=attr-readonly
+ form=attr-form
+ spellcheck=attr-spellcheck
+
+ enter=event-enter
+ }}
{{else}}
{{input class="md-input" id=inputElementId placeholder=placeholder type=type value=value focus-in="focusIn" key-down="keyDown" focus-out="focusOut" disabled=disabled required=required autofocus=autofocus
accept=attr-accept
diff --git a/tests/dummy/app/templates/input.hbs b/tests/dummy/app/templates/input.hbs
index a74d464c8..e1c333c6b 100644
--- a/tests/dummy/app/templates/input.hbs
+++ b/tests/dummy/app/templates/input.hbs
@@ -71,9 +71,88 @@
\{{paper-input placeholder="Phone Number" type="text" value=user.phone icon="phone" md-no-float=''}}
\{{paper-input label="Email (required)" type="email" value=user.email icon="email" icon-class="email" required=true hideAllMessages=true}}
\{{paper-input placeholder="Address" type="text" value=user.address icon="place"}}
-</p>
+</p>{{/code-block}}
+ Input Attributes
+
+ These additional attributes will be passed through to the input helper inside of paper-input.
+ See the Ember Input Helpers for more information.
+ This is an example of using one of the attributes.
+
+
+{{#code-block language="handlebars"}}
+ \{{paper-input attr-tabindex="2"}}{{/code-block}}
+
+ Text Fields
+
+
+
+
+ Ember Paper |
+ Matching Ember Input Helper Attribute |
+
+
+
+ attr-accept | accept |
+ attr-autocomplete | autocomplete |
+ attr-autosave | autosave |
+ attr-form | form |
+ attr-formaction | formaction |
+ attr-formenctype | formenctype |
+ attr-formmethod | formmethod |
+ attr-formnovalidate | formnovalidate |
+ attr-formtarget | formtarget |
+ attr-height | height |
+ attr-inputmode | inputmode |
+ attr-min | min |
+ attr-maxlength | maxlength |
+ attr-max | max |
+ attr-multiple | multiple |
+ attr-name | name |
+ attr-pattern | pattern |
+ attr-readonly | readonly |
+ attr-selectionDirection | selectionDirection |
+ attr-size | size |
+ attr-spellcheck | spellcheck |
+ attr-step | step |
+ attr-tabindex | tabindex |
+ attr-width | width |
+
+
+
+ Text Areas
+
+
+
+
+ Ember Paper |
+ Matching Ember Input Helper Attribute |
+
+
+
+ attr-cols | cols |
+ attr-form | form |
+ attr-maxlength | maxlength |
+ attr-name | name |
+ attr-readonly | readonly |
+ attr-rows | rows |
+ attr-selectionDirection | selectionDirection |
+ attr-selectionEnd | selectionEnd |
+ attr-selectionStart | selectionStart |
+ attr-spellcheck | spellcheck |
+ attr-tabindex | tabindex |
+ attr-wrap | wrap |
+
+
+
+ Events
+
+ You may also pass through an action when the user presses the enter key while on the input field or textarea.
+
+
+ {{#code-block language="handlebars"}}
+ \{{paper-input event-enter="myEnterActionFunctionName"}}{{/code-block}}
+
-{{/code-block}}
{{/paper-content}}
From f79864453634123d7dc44471b1c3bcecc1ae4396 Mon Sep 17 00:00:00 2001
From: Dan Monroe
Date: Wed, 9 Sep 2015 10:13:35 -0400
Subject: [PATCH 4/5] Add support for custom validations in paper-input
component
---
CHANGELOG.md | 3 +
addon/components/paper-input.js | 50 +++++--
tests/dummy/app/controllers/input.js | 34 +++++
tests/dummy/app/templates/input.hbs | 49 ++++++
tests/unit/components/paper-input-test.js | 174 ++++++++++++++++++++++
5 files changed, 301 insertions(+), 9 deletions(-)
create mode 100644 tests/dummy/app/controllers/input.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c37ad2b5..dd2252b0c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# Ember Paper Changelog
+- [#171](https://github.com/miguelcobain/ember-paper/pull/171) Add support for custom validations in paper-input component.
+
+
### 0.2.8 (Aug 19, 2015)
- [#154](https://github.com/miguelcobain/ember-paper/pull/154) Add support for inline paper-icon in paper-input component
- [#152](https://github.com/miguelcobain/ember-paper/pull/152) Add support for .md-actions to {{paper-card}}
diff --git a/addon/components/paper-input.js b/addon/components/paper-input.js
index 096879836..330bda282 100644
--- a/addon/components/paper-input.js
+++ b/addon/components/paper-input.js
@@ -24,13 +24,15 @@ export default BaseFocusable.extend(ColorMixin, FlexMixin, {
}),
iconFloat: Ember.computed.and('icon', 'label'),
+ customValidation: null,
+
validate() {
if (!this.get('isTouched')) {
return false;
}
- var returnValue = false;
+ var valueIsInvalid = false;
var currentValue = this.get('value');
var constraints = [
{
@@ -51,24 +53,54 @@ export default BaseFocusable.extend(ColorMixin, FlexMixin, {
{
attr: 'maxlength',
defaultError: 'Must not exceed ' + this.get('maxlength') + ' characters.',
- isError: () => currentValue && currentValue.length > + this.get('maxlength')
+ isError: () => currentValue && currentValue.length > +this.get('maxlength')
}
];
constraints.some(thisConstraint => {
- if(thisConstraint.isError()) {
+ if (thisConstraint.isError()) {
this.setError(thisConstraint);
- returnValue = true;
+ valueIsInvalid = true;
return true;
}
});
- return returnValue;
+ if (valueIsInvalid === true) {
+ return true;
+ }
+
+ if (!Ember.isEmpty(this.get('customValidation'))) {
+ var validationObjects = Ember.A();
+ var self = this;
+
+ try {
+ if (!Ember.isArray(this.get('customValidation'))) {
+ validationObjects.addObject(this.get('customValidation'));
+ } else {
+ validationObjects = this.get('customValidation');
+ }
+
+ for (var thisValidationObj of validationObjects) {
+ if (typeof thisValidationObj.isError === 'function') {
+ if (thisValidationObj.isError.apply(null, [currentValue])) {
+ self.setError(thisValidationObj);
+ valueIsInvalid = true;
+ break;
+ }
+ }
+ }
+ } catch (error) {
+ Ember.Logger.error('Exception with custom validation: ', error);
+ }
+
+ }
+
+ return valueIsInvalid;
},
setError(constraint) {
- this.set('ng-message', constraint.attr);
- this.set('errortext', this.get(constraint.attr + '-errortext') || constraint.defaultError);
+ this.set('ng-message', constraint.attr || 'custom');
+ this.set('errortext', this.get(constraint.attr + '-errortext') || constraint.defaultError || constraint.errorMessage);
},
actions: {
@@ -76,11 +108,11 @@ export default BaseFocusable.extend(ColorMixin, FlexMixin, {
// We resend action so other components can take use of the actions also ( if they want ).
// Actions must be sent before focusing.
this.sendAction('focus-in', value);
- this.set('focus',true);
+ this.set('focus', true);
},
focusOut(value) {
this.sendAction('focus-out', value);
- this.set('focus',false);
+ this.set('focus', false);
this.set('isTouched', true);
},
keyDown(value, event) {
diff --git a/tests/dummy/app/controllers/input.js b/tests/dummy/app/controllers/input.js
new file mode 100644
index 000000000..5b400a9c8
--- /dev/null
+++ b/tests/dummy/app/controllers/input.js
@@ -0,0 +1,34 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+
+ multipleConstraints: [
+ {
+ 'errorMessage': 'Value is not even',
+ 'isError': (inputValue) => {
+ return (+inputValue % 2) === 1;
+ }
+ },
+ {
+ 'errorMessage': 'Value does not equal 4',
+ 'isError': (inputValue) => {
+ return +inputValue !== 4;
+ }
+ }
+ ],
+
+ singleContraint: {
+ 'errorMessage': 'Value does not equal 16',
+ 'isError': (inputValue) => {
+ return +inputValue !== 16;
+ }
+ },
+
+ emailValidation: {
+ 'errorMessage': 'Please provide email in a valid format',
+ 'isError': (inputValue) => {
+ var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
+ return !emailPattern.test(inputValue);
+ }
+ }
+});
diff --git a/tests/dummy/app/templates/input.hbs b/tests/dummy/app/templates/input.hbs
index e1c333c6b..ce03c47d2 100644
--- a/tests/dummy/app/templates/input.hbs
+++ b/tests/dummy/app/templates/input.hbs
@@ -154,5 +154,54 @@
\{{paper-input event-enter="myEnterActionFunctionName"}}{{/code-block}}
+ Custom Validations
+
+ In addition to {{#code-inline}}required{{/code-inline}}, {{#code-inline}}min{{/code-inline}}, {{#code-inline}}max{{/code-inline}}, and {{#code-inline}}maxlength{{/code-inline}}, you may define your own custom validations.
+ What you need to do is to define an object with two attributes, {{#code-inline}}errorMessage{{/code-inline}} and {{#code-inline}}isError{{/code-inline}}.
+
+
+ - errorMessage This is the text you want to display to the user when there is an error.
+ - isError This is a function that takes one parameter, which is the input's value, and returns true when the value is invalid or false when the value is valid.
+
+
+
+ Here is an example of validating the input value matches typical email formats.
+
+ Template
+ {{#code-block language="handlebars"}}
+ \{{paper-input label="E-mail" type="email" value=email customValidation=emailValidation}}{{/code-block}}
+
+ Define your {{#code-inline}}emailValidation{{/code-inline}} object in your controller.
+{{#code-block language="handlebars"}}
+emailValidation: {
+ 'errorMessage': 'Please provide email in a valid format',
+ 'isError': (inputValue) => {
+ var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
+ return !emailPattern.test(inputValue);
+ }
+}{{/code-block}}
+ {{paper-input label="E-mail" type="email" value=customemail customValidation=emailValidation}}
+
+
+ You may also define multiple custom constraints by using an array of validation objects.
+
+ {{#code-block language="handlebars"}}
+ \{{paper-input label="E-mail" type="email" value=email customValidation=multipleConstraints}}{{/code-block}}
+{{#code-block language="handlebars"}}
+multipleConstraints: [
+ {
+ 'errorMessage': 'Value is not even',
+ 'isError': (inputValue) => {
+ return (+inputValue % 2) === 1;
+ }
+ },
+ {
+ 'errorMessage': 'Value does not equal 4',
+ 'isError': (inputValue) => {
+ return +inputValue !== 4;
+ }
+ }
+];}{{/code-block}}
+ {{paper-input label="Value should be even and equal 4." type="email" value=customMultiple customValidation=multipleConstraints}}
{{/paper-content}}
diff --git a/tests/unit/components/paper-input-test.js b/tests/unit/components/paper-input-test.js
index cd4a50c31..e8ff60645 100644
--- a/tests/unit/components/paper-input-test.js
+++ b/tests/unit/components/paper-input-test.js
@@ -311,3 +311,177 @@ test('validates maxlength with no error', function(assert) {
assert.equal(charCounterDiv[0].innerHTML, '10/10');
});
+
+test('custom validations with one object and error', function(assert) {
+ var inputGroup,
+ errorDiv,
+ customValidationConstraint,
+ component = this.subject(),
+ expectedError = 'Value does not equal 4';
+
+ assert.expect(2);
+
+ customValidationConstraint = {
+ 'errorMessage': 'Value does not equal 4',
+ 'isError': function (inputValue) {
+ return +inputValue !== 4;
+ }
+ };
+
+ component.set('customValidation', customValidationConstraint);
+ component.set('value', '5');
+ component.set('isTouched', true);
+
+ this.render();
+
+ inputGroup = document.getElementsByTagName('md-input-container');
+ assert.equal(inputGroup.length === 1, true);
+
+ errorDiv = document.getElementById('error-input-'+inputGroup[0].id);
+ assert.equal(errorDiv.innerHTML, expectedError, 'Error text does not equal ' + expectedError);
+
+});
+
+test('custom validations with one object and no error', function(assert) {
+ var inputGroup,
+ errorDiv,
+ customValidationConstraint,
+ component = this.subject();
+
+ assert.expect(2);
+
+ customValidationConstraint = {
+ 'errorMessage': 'Value does not equal 4',
+ 'isError': function (inputValue) {
+ return +inputValue !== 4;
+ }
+ };
+
+ component.set('customValidation', customValidationConstraint);
+ component.set('value', '4');
+ component.set('isTouched', true);
+
+ this.render();
+
+ inputGroup = document.getElementsByTagName('md-input-container');
+ assert.equal(inputGroup.length === 1, true);
+
+ errorDiv = document.getElementById('error-input-' + inputGroup[0].id);
+ assert.equal(errorDiv.innerText, '');
+
+});
+
+test('custom validations with multiple constraints and error caught for first constraint', function(assert) {
+ var inputGroup,
+ errorDiv,
+ customValidationArray,
+ component = this.subject(),
+ expectedError = 'Value is not even';
+
+ assert.expect(2);
+
+ customValidationArray = [
+ {
+ 'errorMessage': 'Value is not even',
+ 'isError': function isInputisNotEven(inputValue) {
+ return (+inputValue % 2) === 1;
+ }
+ },
+ {
+ 'errorMessage': 'Value does not equal 4',
+ 'isError': function isInputFour(inputValue) {
+ return +inputValue !== 4;
+ }
+ }
+ ];
+
+ component.set('customValidation', customValidationArray);
+ component.set('value', '5');
+ component.set('isTouched', true);
+
+ this.render();
+
+ inputGroup = document.getElementsByTagName('md-input-container');
+ assert.equal(inputGroup.length === 1, true);
+
+ errorDiv = document.getElementById('error-input-'+inputGroup[0].id);
+ assert.equal(errorDiv.innerHTML, expectedError, 'Error text does not equal ' + expectedError);
+
+});
+
+
+test('custom validations with multiple constraints and error caught for second constraint', function(assert) {
+ var inputGroup,
+ errorDiv,
+ customValidationArray,
+ component = this.subject(),
+ expectedError = 'Value does not equal 4';
+
+ assert.expect(2);
+
+ customValidationArray = [
+ {
+ 'errorMessage': 'Value is not even',
+ 'isError': function isInputisNotEven(inputValue) {
+ return (+inputValue % 2) === 1;
+ }
+ },
+ {
+ 'errorMessage': 'Value does not equal 4',
+ 'isError': function isInputFour(inputValue) {
+ return +inputValue !== 4;
+ }
+ }
+ ];
+
+ component.set('customValidation', customValidationArray);
+ component.set('value', '6');
+ component.set('isTouched', true);
+
+ this.render();
+
+ inputGroup = document.getElementsByTagName('md-input-container');
+ assert.equal(inputGroup.length === 1, true);
+
+ errorDiv = document.getElementById('error-input-'+inputGroup[0].id);
+ assert.equal(errorDiv.innerHTML, expectedError, 'Error text does not equal ' + expectedError);
+
+});
+
+test('custom validations with multiple constraints and no error', function(assert) {
+ var inputGroup,
+ errorDiv,
+ customValidationArray,
+ component = this.subject();
+
+ assert.expect(2);
+
+ customValidationArray = [
+ {
+ 'errorMessage': 'Value is not even',
+ 'isError': function isInputisNotEven(inputValue) {
+ return (+inputValue % 2) === 1;
+ }
+ },
+ {
+ 'errorMessage': 'Value does not equal 4',
+ 'isError': function isInputFour(inputValue) {
+ return +inputValue !== 4;
+ }
+ }
+ ];
+
+ component.set('customValidation', customValidationArray);
+ component.set('value', '4');
+ component.set('isTouched', true);
+
+ this.render();
+
+ inputGroup = document.getElementsByTagName('md-input-container');
+ assert.equal(inputGroup.length === 1, true);
+
+ errorDiv = document.getElementById('error-input-' + inputGroup[0].id);
+ assert.equal(errorDiv.innerText, '');
+
+});
+
From 77b3b60111d275053053f3138316fa56573ea9e9 Mon Sep 17 00:00:00 2001
From: Dan Monroe
Date: Wed, 9 Sep 2015 10:20:50 -0400
Subject: [PATCH 5/5] Revert "Add support for custom validations in paper-input
component"
This reverts commit f79864453634123d7dc44471b1c3bcecc1ae4396.
---
CHANGELOG.md | 3 -
addon/components/paper-input.js | 50 ++-----
tests/dummy/app/controllers/input.js | 34 -----
tests/dummy/app/templates/input.hbs | 49 ------
tests/unit/components/paper-input-test.js | 174 ----------------------
5 files changed, 9 insertions(+), 301 deletions(-)
delete mode 100644 tests/dummy/app/controllers/input.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dd2252b0c..8c37ad2b5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,5 @@
# Ember Paper Changelog
-- [#171](https://github.com/miguelcobain/ember-paper/pull/171) Add support for custom validations in paper-input component.
-
-
### 0.2.8 (Aug 19, 2015)
- [#154](https://github.com/miguelcobain/ember-paper/pull/154) Add support for inline paper-icon in paper-input component
- [#152](https://github.com/miguelcobain/ember-paper/pull/152) Add support for .md-actions to {{paper-card}}
diff --git a/addon/components/paper-input.js b/addon/components/paper-input.js
index 330bda282..096879836 100644
--- a/addon/components/paper-input.js
+++ b/addon/components/paper-input.js
@@ -24,15 +24,13 @@ export default BaseFocusable.extend(ColorMixin, FlexMixin, {
}),
iconFloat: Ember.computed.and('icon', 'label'),
- customValidation: null,
-
validate() {
if (!this.get('isTouched')) {
return false;
}
- var valueIsInvalid = false;
+ var returnValue = false;
var currentValue = this.get('value');
var constraints = [
{
@@ -53,54 +51,24 @@ export default BaseFocusable.extend(ColorMixin, FlexMixin, {
{
attr: 'maxlength',
defaultError: 'Must not exceed ' + this.get('maxlength') + ' characters.',
- isError: () => currentValue && currentValue.length > +this.get('maxlength')
+ isError: () => currentValue && currentValue.length > + this.get('maxlength')
}
];
constraints.some(thisConstraint => {
- if (thisConstraint.isError()) {
+ if(thisConstraint.isError()) {
this.setError(thisConstraint);
- valueIsInvalid = true;
+ returnValue = true;
return true;
}
});
- if (valueIsInvalid === true) {
- return true;
- }
-
- if (!Ember.isEmpty(this.get('customValidation'))) {
- var validationObjects = Ember.A();
- var self = this;
-
- try {
- if (!Ember.isArray(this.get('customValidation'))) {
- validationObjects.addObject(this.get('customValidation'));
- } else {
- validationObjects = this.get('customValidation');
- }
-
- for (var thisValidationObj of validationObjects) {
- if (typeof thisValidationObj.isError === 'function') {
- if (thisValidationObj.isError.apply(null, [currentValue])) {
- self.setError(thisValidationObj);
- valueIsInvalid = true;
- break;
- }
- }
- }
- } catch (error) {
- Ember.Logger.error('Exception with custom validation: ', error);
- }
-
- }
-
- return valueIsInvalid;
+ return returnValue;
},
setError(constraint) {
- this.set('ng-message', constraint.attr || 'custom');
- this.set('errortext', this.get(constraint.attr + '-errortext') || constraint.defaultError || constraint.errorMessage);
+ this.set('ng-message', constraint.attr);
+ this.set('errortext', this.get(constraint.attr + '-errortext') || constraint.defaultError);
},
actions: {
@@ -108,11 +76,11 @@ export default BaseFocusable.extend(ColorMixin, FlexMixin, {
// We resend action so other components can take use of the actions also ( if they want ).
// Actions must be sent before focusing.
this.sendAction('focus-in', value);
- this.set('focus', true);
+ this.set('focus',true);
},
focusOut(value) {
this.sendAction('focus-out', value);
- this.set('focus', false);
+ this.set('focus',false);
this.set('isTouched', true);
},
keyDown(value, event) {
diff --git a/tests/dummy/app/controllers/input.js b/tests/dummy/app/controllers/input.js
deleted file mode 100644
index 5b400a9c8..000000000
--- a/tests/dummy/app/controllers/input.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import Ember from 'ember';
-
-export default Ember.Controller.extend({
-
- multipleConstraints: [
- {
- 'errorMessage': 'Value is not even',
- 'isError': (inputValue) => {
- return (+inputValue % 2) === 1;
- }
- },
- {
- 'errorMessage': 'Value does not equal 4',
- 'isError': (inputValue) => {
- return +inputValue !== 4;
- }
- }
- ],
-
- singleContraint: {
- 'errorMessage': 'Value does not equal 16',
- 'isError': (inputValue) => {
- return +inputValue !== 16;
- }
- },
-
- emailValidation: {
- 'errorMessage': 'Please provide email in a valid format',
- 'isError': (inputValue) => {
- var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
- return !emailPattern.test(inputValue);
- }
- }
-});
diff --git a/tests/dummy/app/templates/input.hbs b/tests/dummy/app/templates/input.hbs
index ce03c47d2..e1c333c6b 100644
--- a/tests/dummy/app/templates/input.hbs
+++ b/tests/dummy/app/templates/input.hbs
@@ -154,54 +154,5 @@
\{{paper-input event-enter="myEnterActionFunctionName"}}{{/code-block}}
- Custom Validations
-
- In addition to {{#code-inline}}required{{/code-inline}}, {{#code-inline}}min{{/code-inline}}, {{#code-inline}}max{{/code-inline}}, and {{#code-inline}}maxlength{{/code-inline}}, you may define your own custom validations.
- What you need to do is to define an object with two attributes, {{#code-inline}}errorMessage{{/code-inline}} and {{#code-inline}}isError{{/code-inline}}.
-
-
- - errorMessage This is the text you want to display to the user when there is an error.
- - isError This is a function that takes one parameter, which is the input's value, and returns true when the value is invalid or false when the value is valid.
-
-
-
- Here is an example of validating the input value matches typical email formats.
-
- Template
- {{#code-block language="handlebars"}}
- \{{paper-input label="E-mail" type="email" value=email customValidation=emailValidation}}{{/code-block}}
-
- Define your {{#code-inline}}emailValidation{{/code-inline}} object in your controller.
-{{#code-block language="handlebars"}}
-emailValidation: {
- 'errorMessage': 'Please provide email in a valid format',
- 'isError': (inputValue) => {
- var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
- return !emailPattern.test(inputValue);
- }
-}{{/code-block}}
- {{paper-input label="E-mail" type="email" value=customemail customValidation=emailValidation}}
-
-
- You may also define multiple custom constraints by using an array of validation objects.
-
- {{#code-block language="handlebars"}}
- \{{paper-input label="E-mail" type="email" value=email customValidation=multipleConstraints}}{{/code-block}}
-{{#code-block language="handlebars"}}
-multipleConstraints: [
- {
- 'errorMessage': 'Value is not even',
- 'isError': (inputValue) => {
- return (+inputValue % 2) === 1;
- }
- },
- {
- 'errorMessage': 'Value does not equal 4',
- 'isError': (inputValue) => {
- return +inputValue !== 4;
- }
- }
-];}{{/code-block}}
- {{paper-input label="Value should be even and equal 4." type="email" value=customMultiple customValidation=multipleConstraints}}
{{/paper-content}}
diff --git a/tests/unit/components/paper-input-test.js b/tests/unit/components/paper-input-test.js
index e8ff60645..cd4a50c31 100644
--- a/tests/unit/components/paper-input-test.js
+++ b/tests/unit/components/paper-input-test.js
@@ -311,177 +311,3 @@ test('validates maxlength with no error', function(assert) {
assert.equal(charCounterDiv[0].innerHTML, '10/10');
});
-
-test('custom validations with one object and error', function(assert) {
- var inputGroup,
- errorDiv,
- customValidationConstraint,
- component = this.subject(),
- expectedError = 'Value does not equal 4';
-
- assert.expect(2);
-
- customValidationConstraint = {
- 'errorMessage': 'Value does not equal 4',
- 'isError': function (inputValue) {
- return +inputValue !== 4;
- }
- };
-
- component.set('customValidation', customValidationConstraint);
- component.set('value', '5');
- component.set('isTouched', true);
-
- this.render();
-
- inputGroup = document.getElementsByTagName('md-input-container');
- assert.equal(inputGroup.length === 1, true);
-
- errorDiv = document.getElementById('error-input-'+inputGroup[0].id);
- assert.equal(errorDiv.innerHTML, expectedError, 'Error text does not equal ' + expectedError);
-
-});
-
-test('custom validations with one object and no error', function(assert) {
- var inputGroup,
- errorDiv,
- customValidationConstraint,
- component = this.subject();
-
- assert.expect(2);
-
- customValidationConstraint = {
- 'errorMessage': 'Value does not equal 4',
- 'isError': function (inputValue) {
- return +inputValue !== 4;
- }
- };
-
- component.set('customValidation', customValidationConstraint);
- component.set('value', '4');
- component.set('isTouched', true);
-
- this.render();
-
- inputGroup = document.getElementsByTagName('md-input-container');
- assert.equal(inputGroup.length === 1, true);
-
- errorDiv = document.getElementById('error-input-' + inputGroup[0].id);
- assert.equal(errorDiv.innerText, '');
-
-});
-
-test('custom validations with multiple constraints and error caught for first constraint', function(assert) {
- var inputGroup,
- errorDiv,
- customValidationArray,
- component = this.subject(),
- expectedError = 'Value is not even';
-
- assert.expect(2);
-
- customValidationArray = [
- {
- 'errorMessage': 'Value is not even',
- 'isError': function isInputisNotEven(inputValue) {
- return (+inputValue % 2) === 1;
- }
- },
- {
- 'errorMessage': 'Value does not equal 4',
- 'isError': function isInputFour(inputValue) {
- return +inputValue !== 4;
- }
- }
- ];
-
- component.set('customValidation', customValidationArray);
- component.set('value', '5');
- component.set('isTouched', true);
-
- this.render();
-
- inputGroup = document.getElementsByTagName('md-input-container');
- assert.equal(inputGroup.length === 1, true);
-
- errorDiv = document.getElementById('error-input-'+inputGroup[0].id);
- assert.equal(errorDiv.innerHTML, expectedError, 'Error text does not equal ' + expectedError);
-
-});
-
-
-test('custom validations with multiple constraints and error caught for second constraint', function(assert) {
- var inputGroup,
- errorDiv,
- customValidationArray,
- component = this.subject(),
- expectedError = 'Value does not equal 4';
-
- assert.expect(2);
-
- customValidationArray = [
- {
- 'errorMessage': 'Value is not even',
- 'isError': function isInputisNotEven(inputValue) {
- return (+inputValue % 2) === 1;
- }
- },
- {
- 'errorMessage': 'Value does not equal 4',
- 'isError': function isInputFour(inputValue) {
- return +inputValue !== 4;
- }
- }
- ];
-
- component.set('customValidation', customValidationArray);
- component.set('value', '6');
- component.set('isTouched', true);
-
- this.render();
-
- inputGroup = document.getElementsByTagName('md-input-container');
- assert.equal(inputGroup.length === 1, true);
-
- errorDiv = document.getElementById('error-input-'+inputGroup[0].id);
- assert.equal(errorDiv.innerHTML, expectedError, 'Error text does not equal ' + expectedError);
-
-});
-
-test('custom validations with multiple constraints and no error', function(assert) {
- var inputGroup,
- errorDiv,
- customValidationArray,
- component = this.subject();
-
- assert.expect(2);
-
- customValidationArray = [
- {
- 'errorMessage': 'Value is not even',
- 'isError': function isInputisNotEven(inputValue) {
- return (+inputValue % 2) === 1;
- }
- },
- {
- 'errorMessage': 'Value does not equal 4',
- 'isError': function isInputFour(inputValue) {
- return +inputValue !== 4;
- }
- }
- ];
-
- component.set('customValidation', customValidationArray);
- component.set('value', '4');
- component.set('isTouched', true);
-
- this.render();
-
- inputGroup = document.getElementsByTagName('md-input-container');
- assert.equal(inputGroup.length === 1, true);
-
- errorDiv = document.getElementById('error-input-' + inputGroup[0].id);
- assert.equal(errorDiv.innerText, '');
-
-});
-