OLD | NEW |
1 | 1 |
2 | 2 |
| 3 /* |
| 4 `<iron-input>` adds two-way binding and custom validators using `Polymer.IronVal
idatorBehavior` |
| 5 to `<input>`. |
| 6 |
| 7 ### Two-way binding |
| 8 |
| 9 By default you can only get notified of changes to an `input`'s `value` due to u
ser input: |
| 10 |
| 11 <input value="{{myValue::input}}"> |
| 12 |
| 13 `iron-input` adds the `bind-value` property that mirrors the `value` property, a
nd can be used |
| 14 for two-way data binding. `bind-value` will notify if it is changed either by us
er input or by script. |
| 15 |
| 16 <input is="iron-input" bind-value="{{myValue}}"> |
| 17 |
| 18 ### Custom validators |
| 19 |
| 20 You can use custom validators that implement `Polymer.IronValidatorBehavior` wit
h `<iron-input>`. |
| 21 |
| 22 <input is="iron-input" validator="my-custom-validator"> |
| 23 |
| 24 ### Stopping invalid input |
| 25 |
| 26 It may be desirable to only allow users to enter certain characters. You can use
the |
| 27 `prevent-invalid-input` and `allowed-pattern` attributes together to accomplish
this. This feature |
| 28 is separate from validation, and `allowed-pattern` does not affect how the input
is validated. |
| 29 |
| 30 <!-- only allow characters that match [0-9] --> |
| 31 <input is="iron-input" prevent-invaild-input allowed-pattern="[0-9]"> |
| 32 |
| 33 @hero hero.svg |
| 34 @demo demo/index.html |
| 35 */ |
| 36 |
3 Polymer({ | 37 Polymer({ |
4 | 38 |
5 is: 'iron-input', | 39 is: 'iron-input', |
6 | 40 |
7 extends: 'input', | 41 extends: 'input', |
8 | 42 |
| 43 behaviors: [ |
| 44 Polymer.IronValidatableBehavior |
| 45 ], |
| 46 |
9 properties: { | 47 properties: { |
10 | 48 |
11 /** | 49 /** |
12 * Use this property instead of `value` for two-way data binding. | 50 * Use this property instead of `value` for two-way data binding. |
13 */ | 51 */ |
14 bindValue: { | 52 bindValue: { |
15 observer: '_bindValueChanged', | 53 observer: '_bindValueChanged', |
16 type: String | 54 type: String |
17 }, | 55 }, |
18 | 56 |
19 /** | 57 /** |
20 * Set to true to prevent the user from entering invalid input or setting | 58 * Set to true to prevent the user from entering invalid input. The new in
put characters are |
21 * invalid `bindValue`. | 59 * matched with `allowedPattern` if it is set, otherwise it will use the `
pattern` attribute if |
| 60 * set, or the `type` attribute (only supported for `type=number`). |
22 */ | 61 */ |
23 preventInvalidInput: { | 62 preventInvalidInput: { |
24 type: Boolean | 63 type: Boolean |
25 }, | 64 }, |
26 | 65 |
| 66 /** |
| 67 * Regular expression to match valid input characters. |
| 68 */ |
| 69 allowedPattern: { |
| 70 type: String |
| 71 }, |
| 72 |
27 _previousValidInput: { | 73 _previousValidInput: { |
28 type: String, | 74 type: String, |
29 value: '' | 75 value: '' |
30 } | 76 } |
31 | 77 |
32 }, | 78 }, |
33 | 79 |
34 listeners: { | 80 listeners: { |
35 'input': '_onInput' | 81 'input': '_onInput', |
| 82 'keydown': '_onKeydown' |
| 83 }, |
| 84 |
| 85 get _patternRegExp() { |
| 86 var pattern; |
| 87 if (this.allowedPattern) { |
| 88 pattern = new RegExp(this.allowedPattern); |
| 89 } else if (this.pattern) { |
| 90 pattern = new RegExp(this.pattern); |
| 91 } else { |
| 92 switch (this.type) { |
| 93 case 'number': |
| 94 pattern = /[0-9.,e-]/; |
| 95 break; |
| 96 } |
| 97 } |
| 98 return pattern; |
36 }, | 99 }, |
37 | 100 |
38 ready: function() { | 101 ready: function() { |
39 this._validateValue(); | |
40 this.bindValue = this.value; | 102 this.bindValue = this.value; |
41 }, | 103 }, |
42 | 104 |
43 _bindValueChanged: function() { | 105 _bindValueChanged: function() { |
44 // If this was called as a result of user input, then |_validateValue| | 106 if (this.value !== this.bindValue) { |
45 // has already been called in |_onInput|, and it doesn't need to be | |
46 // called again. | |
47 if (this.value != this.bindValue) { | |
48 this.value = this.bindValue; | 107 this.value = this.bindValue; |
49 this._validateValue(); | |
50 } | 108 } |
51 | |
52 // manually notify because we don't want to notify until after setting val
ue | 109 // manually notify because we don't want to notify until after setting val
ue |
53 this.fire('bind-value-changed', {value: this.bindValue}); | 110 this.fire('bind-value-changed', {value: this.bindValue}); |
54 }, | 111 }, |
55 | 112 |
56 _onInput: function() { | 113 _onInput: function() { |
57 this._validateValue(); | 114 this.bindValue = this.value; |
58 }, | 115 }, |
59 | 116 |
60 _validateValue: function() { | 117 _isPrintable: function(keyCode) { |
61 var value; | 118 var printable = |
62 if (this.preventInvalidInput && !this.validity.valid) { | 119 (keyCode > 47 && keyCode < 58) || // number keys |
63 value = this._previousValidInput; | 120 keyCode == 32 || keyCode == 13 || // spacebar & return key |
| 121 (keyCode > 64 && keyCode < 91) || // letter keys |
| 122 (keyCode > 95 && keyCode < 112) || // numpad keys |
| 123 (keyCode > 185 && keyCode < 193) || // ;=,-./` (in order) |
| 124 (keyCode > 218 && keyCode < 223); // [\]' (in order) |
| 125 return printable; |
| 126 }, |
| 127 |
| 128 // convert printable numpad keys to number keys |
| 129 _correctNumpadKeys: function(keyCode) { |
| 130 return (keyCode > 95 && keyCode < 112) ? keyCode - 48 : keyCode; |
| 131 }, |
| 132 |
| 133 _onKeydown: function(event) { |
| 134 if (!this.preventInvalidInput && this.type !== 'number') { |
| 135 return; |
| 136 } |
| 137 var regexp = this._patternRegExp; |
| 138 if (!regexp) { |
| 139 return; |
| 140 } |
| 141 var thisChar = String.fromCharCode(this._correctNumpadKeys(event.keyCode))
; |
| 142 if (this._isPrintable(event.keyCode) && !regexp.test(thisChar)) { |
| 143 event.preventDefault(); |
| 144 } |
| 145 }, |
| 146 |
| 147 /** |
| 148 * Returns true if `value` is valid. The validator provided in `validator` w
ill be used first, |
| 149 * then any constraints. |
| 150 * @return {Boolean} True if the value is valid. |
| 151 */ |
| 152 validate: function() { |
| 153 // Empty, non-required input is valid. |
| 154 if (!this.required && this.value == '') |
| 155 return true; |
| 156 |
| 157 var valid; |
| 158 if (this.hasValidator()) { |
| 159 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value); |
64 } else { | 160 } else { |
65 value = this._previousValidInput = this.value; | 161 this.invalid = !this.validity.valid; |
| 162 valid = this.validity.valid; |
66 } | 163 } |
67 this.bindValue = this.value = value; | 164 this.fire('iron-input-validate'); |
| 165 return valid; |
68 } | 166 } |
69 | 167 |
70 }) | 168 }); |
| 169 |
| 170 /* |
| 171 The `iron-input-validate` event is fired whenever `validate()` is called. |
| 172 @event iron-input-validate |
| 173 */ |
| 174 |
OLD | NEW |