forked from PolymerElements/iron-validatable-behavior
-
Notifications
You must be signed in to change notification settings - Fork 0
/
iron-validatable-behavior.html
266 lines (233 loc) · 9.19 KB
/
iron-validatable-behavior.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-meta/iron-meta.html">
<script>
(function() {
/**
* Singleton IronMeta instances.
*/
var customMeta = null;
var nativeMeta = null;
/**
* Use `Polymer.IronValidatableBehavior` to implement an element that validates user input.
* Use the related `Polymer.IronValidatorBehavior` to add custom validation logic to an iron-input.
*
* By default, an `<iron-form>` element validates its fields when the user presses the submit button.
* To validate a form imperatively, call the form's `validate()` method, which in turn will
* call `validate()` on all its children. By using `Polymer.IronValidatableBehavior`, your
* custom element will get a public `validate()`, which
* will return the validity of the element, and a corresponding `invalid` attribute,
* which can be used for styling.
*
* To implement the custom validation logic of your element, you must override
* the protected `_getValidity()` method of this behaviour, rather than `validate()`.
* See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/simple-element.html)
* for an example.
*
* ### Interaction states
* - dirty: True when user has focused and left(blurred) the field
* - touched: True when user has typed in something in the input field
*
* For the outside world, these values may only be read. In fundamental form components and behaviors using this be behavior
* (for instance the `IronValidationTriggerBehavior` ) these read only values may be altered (do this with _setDirty and _setTouched respectively).
*
*
* ### Accessibility
*
* Changing the `invalid` property, either manually or by calling `validate()` will update the `aria-invalid` attribute.
*
* @demo demo/index.html
* @demo demo/old-vs-new/index.html Shows differences between new and old API. Also shows the interaction states in combination with validation-trigger-behavior
* @polymerBehavior
*/
Polymer.IronValidatableBehavior = {
properties: {
/**
* Name of the validator(s) to use.
* Accepts a list of validators, separated by spaces.
* Note that the order of the validators determines the priority of the error messages.
*/
validator: {
type: String
},
/**
* True if the last call to `validate` is invalid.
*/
invalid: {
notify: true,
reflectToAttribute: true,
type: Boolean,
value: false
},
/**
* This property is deprecated and should not be used. Use the global
* validator meta singleton, `Polymer.IronValidatableBehaviorMeta` instead.
*/
_validatorMeta: {
type: Object
},
/**
* Namespace for this validator. This property is deprecated and should
* not be used. For all intents and purposes, please consider it a
* read-only, config-time property.
*/
validatorType: {
type: String,
value: 'validator'
},
_validator: {
type: Object,
computed: '__computeValidator(validator)'
},
/**
* Array holding error objects for the current state of the validatable element.
* Each error has the following keys:
* <ul>
* <li><b>validator</b> (String) : name of custom validator instance with IronValidatorBehavior</li>
* <li><b>message</b> (String) : message that is assigned to the validator instance</li>
* <li><b>priority</b> (Number) : priority of the error message, based on order supplied in validator property</li>
* </ul>
*/
errors: {
type: Array,
readOnly: true,
notify: true,
value: function() {
return [];
}
},
/**
* The id used to connect the validator instance implementing IronValidatableBehavior(having a 'for' property)
* to the validatable. This is useful for validator instances containing custom messages.
*/
validatableId: {
type: String,
value: ''
},
/**
* This boolean represent state about how a user has interacted with a form, meant to be used for UI updates about validation state of the input.
* True when user has focused and left(blurred) the field.
* Note this field will be reset when a user leaves a field when it's empty: the user will start with a clean slave the next time he will interact with the input
*/
touched: {
type: Boolean,
readOnly: true,
value: false
},
/**
* This boolean represent state about how a user has interacted with a form, meant to be used for UI updates about validation state of the input.
* True when user has typed in something in the input field.
*/
dirty: {
type: Boolean,
readOnly: true,
value: false
}
},
observers: [
'_invalidChanged(invalid)'
],
registered: function() {
customMeta = new Polymer.IronMeta({type: 'validator'});
nativeMeta = new Polymer.IronMeta({type: 'native-validator'});
},
_invalidChanged: function() {
if (this.invalid) {
this.setAttribute('aria-invalid', 'true');
} else {
this.removeAttribute('aria-invalid');
}
},
/**
* @return {boolean} True if the validator `validator` exists.
*/
hasValidator: function() {
return this._validator != null;
},
/**
* Returns true if the `value` is valid, and updates `invalid`. If you want
* your element to have custom validation logic, do not override this method;
* override `_getValidity(value)` instead.
* @param {Object} value The value to be validated. By default, it is passed
* to the validator's `validate()` function, if a validator is set.
* @return {boolean} True if `value` is valid.
*/
validate: function(value) {
this.invalid = !this._getValidity(value);
return !this.invalid;
},
/**
* Returns true if `value` is valid. By default, it is passed
* to the validator's `validate()` function, if a validator is set. You
* should override this method if you want to implement custom validity
* logic for your element.
*
* @param {Object} value The value to be validated.
* @return {boolean} True if `value` is valid.
*/
_getValidity: function(value) {
this._fillErrorArray(value);
return this.errors.length === 0;
},
/**
* Fills the errors property with objects as described in errors documentation.
* @param {Object} value The value to be validated.
*/
_fillErrorArray: function(value) {
var index = 0;
this._setErrors([]);
// Fill error array that is prioritized based on order of arguments in validator attribute
for (var v in this._validator) {
if (!this._validator[v].validate(value, this)) {
this.push('errors', {
validator: this._validator[v].validatorName,
message: this._validator[v].message,
priority: index
});
index++;
}
}
},
/**
* Creates an object with multiple validators.
*
* @return {Object} validators The validators to be executed.
*/
__computeValidator: function() {
var result = {};
var suffix = '--' + this.validatableId; // Suffix needed for specific instances of custom validators, overriding the default error message
var validators = this.validator.replace(/\s+/g, ' ').split(' ');
// Gather all meta information from custom and native validators
var meta = {custom: customMeta, native: nativeMeta};
validators.forEach(function(v) {
// Custom validators need to be web components and will therefore always contain a hyphen.
// Native validators (think of required, maxlength etc.) never contain a hyphen.
var type = v.indexOf('-') !== -1 ? 'custom' : 'native';
// Custom instance exists
if (meta[type] && meta[type].byKey(v + suffix)) {
result[v] = meta[type].byKey(v + suffix);
}
// Default instance exists
else if (meta[type] && meta[type].byKey(v)) {
result[v] = meta[type].byKey(v);
}
// No instance at all, create one for custom validators.
// (Instantiating native validators via iron-native validator wouldn't make sense here, since
// they don't have messages by default and an instance will be present if message is supplied. )
else if (type === 'custom' && (!meta[type] || !meta[type].byKey(v))) {
result[v] = document.createElement(v);
}
}, this);
return result;
}
};
}());
</script>