OLD | NEW |
| (Empty) |
1 | |
2 /* | |
3 ``<iron-form>` is an HTML `<form>` element that can validate and submit any cust
om | |
4 elements that implement `Polymer.IronFormElementBehavior`, as well as any | |
5 native HTML elements. | |
6 | |
7 It supports both `get` and `post` methods, and uses an `iron-ajax` element to | |
8 submit the form data to the action URL. | |
9 | |
10 Example: | |
11 | |
12 <form is="iron-form" id="form" method="post" action="/form/handler"> | |
13 <paper-input name="name" label="name"></paper-input> | |
14 <input name="address"> | |
15 ... | |
16 </form> | |
17 | |
18 By default, a native `<button>` element will submit this form. However, if you | |
19 want to submit it from a custom element's click handler, you need to explicitly | |
20 call the form's `submit` method. | |
21 | |
22 Example: | |
23 | |
24 <paper-button raised onclick="submitForm()">Submit</paper-button> | |
25 | |
26 function submitForm() { | |
27 document.getElementById('form').submit(); | |
28 } | |
29 | |
30 @demo demo/index.html | |
31 */ | |
32 | |
33 Polymer({ | |
34 | |
35 is: 'iron-form', | |
36 | |
37 extends: 'form', | |
38 | |
39 /** | |
40 * Fired if the form cannot be submitted because it's invalid. | |
41 * | |
42 * @event iron-form-invalid | |
43 */ | |
44 | |
45 /** | |
46 * Fired after the form is submitted. | |
47 * | |
48 * @event iron-form-submit | |
49 */ | |
50 | |
51 /** | |
52 * Fired after the form is submitted and a response is received. | |
53 * | |
54 * @event iron-form-response | |
55 */ | |
56 | |
57 /** | |
58 * Fired after the form is submitted and an error is received. | |
59 * | |
60 * @event iron-form-error | |
61 */ | |
62 | |
63 listeners: { | |
64 'iron-form-element-register': '_registerElement', | |
65 'submit': '_onSubmit' | |
66 }, | |
67 | |
68 ready: function() { | |
69 // Object that handles the ajax form submission request. | |
70 this._requestBot = document.createElement('iron-ajax'); | |
71 this._requestBot.addEventListener('response', this._handleFormResponse.bin
d(this)); | |
72 this._requestBot.addEventListener('error', this._handleFormError.bind(this
)); | |
73 | |
74 // Holds all the custom elements registered with this form. | |
75 this._customElements = []; | |
76 }, | |
77 | |
78 /** | |
79 * Called to submit the form. | |
80 */ | |
81 submit: function() { | |
82 if (!this.noValidate && !this._validate()) { | |
83 | |
84 // In order to trigger the native browser invalid-form UI, we need | |
85 // to do perform a fake form submit. | |
86 this._doFakeSubmitForValidation(); | |
87 this.fire('iron-form-invalid'); | |
88 return; | |
89 } | |
90 | |
91 var json = this.serialize(); | |
92 | |
93 this._requestBot.url = this.action; | |
94 this._requestBot.method = this.method; | |
95 this._requestBot.params = json; | |
96 | |
97 if (this.method == 'POST') { | |
98 this._requestBot.body = JSON.stringify(json); | |
99 } | |
100 | |
101 this._requestBot.generateRequest(); | |
102 this.fire('iron-form-submit', json); | |
103 }, | |
104 | |
105 _onSubmit: function(event) { | |
106 this.submit(); | |
107 | |
108 // Don't perform a page refresh. | |
109 if (event) { | |
110 event.preventDefault(); | |
111 } | |
112 | |
113 return false; | |
114 }, | |
115 | |
116 /** | |
117 * Returns a json object containing name/value pairs for all the registered | |
118 * custom components and native elements of the form. If there are elements | |
119 * with duplicate names, then their values will get aggregated into an | |
120 * array of values. | |
121 */ | |
122 serialize: function() { | |
123 var json = {}; | |
124 | |
125 function addSerializedElement(el) { | |
126 // If the name doesn't exist, add it. Otherwise, serialize it to | |
127 // an array, | |
128 if (!json[el.name]) { | |
129 json[el.name] = el.value; | |
130 } else { | |
131 if (!Array.isArray(json[el.name])) { | |
132 json[el.name] = [json[el.name]]; | |
133 } | |
134 json[el.name].push(el.value); | |
135 } | |
136 } | |
137 | |
138 // Go through all of the registered custom components. | |
139 for (var el, i = 0; el = this._customElements[i], i < this._customElements
.length; i++) { | |
140 if (el.name) { | |
141 addSerializedElement(el); | |
142 } | |
143 } | |
144 | |
145 // Also go through the form's native elements. | |
146 for (var el, i = 0; el = this.elements[i], i < this.elements.length; i++)
{ | |
147 // Checkboxes and radio buttons should only use their value if they're c
hecked. | |
148 // Also, custom elements that extend native elements (like an | |
149 // `<input is="fancy-input">`) will appear in both lists. Since they | |
150 // were already added as a custom element, they don't need | |
151 // to be re-added. | |
152 if (!el.name || !this._useValue(el) || | |
153 (el.hasAttribute('is') && json[el.name])) { | |
154 continue; | |
155 } | |
156 addSerializedElement(el); | |
157 } | |
158 | |
159 return json; | |
160 }, | |
161 | |
162 _handleFormResponse: function (event) { | |
163 this.fire('iron-form-response', event.detail.response); | |
164 }, | |
165 | |
166 _handleFormError: function (event) { | |
167 this.fire('iron-form-error', event.detail); | |
168 }, | |
169 | |
170 _registerElement: function(e) { | |
171 this._customElements.push(e.target); | |
172 }, | |
173 | |
174 _validate: function() { | |
175 var valid = true; | |
176 | |
177 // Validate all the custom elements. | |
178 var validatable; | |
179 for (var el, i = 0; el = this._customElements[i], i < this._customElements
.length; i++) { | |
180 if (el.required) { | |
181 validatable = /** @type {{validate: (function() : boolean)}} */ (el); | |
182 valid = validatable.validate() && valid; | |
183 } | |
184 } | |
185 | |
186 // Validate the form's native elements. | |
187 for (var el, i = 0; el = this.elements[i], i < this.elements.length; i++)
{ | |
188 // Custom elements that extend a native element will also appear in | |
189 // this list, but they've already been validated. | |
190 if (!el.hasAttribute('is') && el.willValidate && el.checkValidity) { | |
191 valid = el.checkValidity() && valid; | |
192 } | |
193 } | |
194 | |
195 return valid; | |
196 }, | |
197 | |
198 _useValue: function(el) { | |
199 // Checkboxes and radio buttons should only use their value if they're che
cked. | |
200 if (el.type !== 'checkbox' && el.type !== 'radio') { | |
201 return true; | |
202 } else { | |
203 return el.checked; | |
204 } | |
205 }, | |
206 | |
207 _doFakeSubmitForValidation: function() { | |
208 var fakeSubmit = document.createElement('input'); | |
209 fakeSubmit.setAttribute('type', 'submit'); | |
210 fakeSubmit.style.display = 'none'; | |
211 this.appendChild(fakeSubmit); | |
212 | |
213 fakeSubmit.click(); | |
214 | |
215 this.removeChild(fakeSubmit); | |
216 } | |
217 | |
218 }); | |
219 | |
OLD | NEW |