0
# Form Handling
1
2
Form serialization and element management utilities for handling form submissions, data collection, and form state management in Rails UJS.
3
4
## Capabilities
5
6
### Form Serialization
7
8
Converts form elements and their data into URL-encoded strings suitable for HTTP requests.
9
10
```javascript { .api }
11
/**
12
* Serialize form or element data to URL-encoded string
13
* @param element - Form element or individual input to serialize
14
* @param additionalParam - Optional additional parameter to include
15
* @returns URL-encoded string of form data
16
*/
17
function serializeElement(element: Element, additionalParam?: {name: string, value: string}): string;
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
const form = document.querySelector("form");
24
25
// Serialize entire form
26
const formData = Rails.serializeElement(form);
27
console.log(formData); // "title=Hello&body=World&commit=Create"
28
29
// Serialize with additional parameter
30
const dataWithToken = Rails.serializeElement(form, {
31
name: "authenticity_token",
32
value: "abc123"
33
});
34
35
// Serialize individual input
36
const input = document.querySelector("input[name=title]");
37
const inputData = Rails.serializeElement(input);
38
console.log(inputData); // "title=Hello"
39
40
// Used in AJAX requests
41
Rails.ajax({
42
type: "POST",
43
url: "/posts",
44
data: Rails.serializeElement(form)
45
});
46
```
47
48
### Form Element Selection
49
50
Gets form elements that match a specific selector, handling both forms and individual elements.
51
52
```javascript { .api }
53
/**
54
* Get form elements matching selector
55
* @param form - Form element or container element
56
* @param selector - CSS selector for elements to find
57
* @returns Array of matching elements
58
*/
59
function formElements(form: Element, selector: string): Element[];
60
```
61
62
**Usage Examples:**
63
64
```javascript
65
const form = document.querySelector("form");
66
67
// Get all submit buttons in form
68
const submitButtons = Rails.formElements(form, "input[type=submit], button[type=submit]");
69
70
// Get elements to disable during submission
71
const disableElements = Rails.formElements(form, "[data-disable-with]");
72
disableElements.forEach(el => Rails.disableElement(el));
73
74
// Get file inputs for special handling
75
const fileInputs = Rails.formElements(form, "input[type=file]");
76
77
// Works with non-form containers too
78
const container = document.querySelector(".form-container");
79
const inputs = Rails.formElements(container, "input, select, textarea");
80
```
81
82
### Submit Button Tracking
83
84
Handles submit button clicks to track which button was used for form submission.
85
86
```javascript { .api }
87
/**
88
* Handle form submit button clicks to track submission context
89
* @param event - Click event from submit button
90
*/
91
function formSubmitButtonClick(event: Event): void;
92
```
93
94
**Usage Examples:**
95
96
```javascript
97
// Automatically handled by Rails UJS for these elements:
98
// form input[type=submit]
99
// form input[type=image]
100
// form button[type=submit]
101
// form button:not([type])
102
// input[type=submit][form]
103
// button[type=submit][form]
104
105
// The clicked button info is stored and used in form submission:
106
const form = document.querySelector("form");
107
const submitButton = form.querySelector("button[name=commit]");
108
109
// After button click, Rails UJS stores:
110
// Rails.getData(form, "ujs:submit-button") = { name: "commit", value: "Create" }
111
// Rails.getData(form, "ujs:formnovalidate-button") = button.formNoValidate
112
// Rails.getData(form, "ujs:submit-button-formaction") = button.formAction
113
// Rails.getData(form, "ujs:submit-button-formmethod") = button.formMethod
114
```
115
116
## Form Serialization Details
117
118
### Included Elements
119
120
The serialization process includes:
121
122
- **Text inputs**: `input[type=text]`, `input[type=email]`, etc.
123
- **Textareas**: All `<textarea>` elements
124
- **Select elements**: Single and multiple select dropdowns
125
- **Checkboxes**: Only checked checkboxes
126
- **Radio buttons**: Only selected radio buttons
127
- **Hidden inputs**: `input[type=hidden]`
128
- **Submit buttons**: The clicked submit button (if any)
129
130
### Excluded Elements
131
132
Elements that are NOT serialized:
133
134
- **Disabled elements**: `[disabled]` attribute present
135
- **Elements without names**: Missing `name` attribute
136
- **Fieldset disabled children**: Elements inside `<fieldset disabled>`
137
- **Unchecked checkboxes**: `input[type=checkbox]:not(:checked)`
138
- **Unselected radios**: `input[type=radio]:not(:checked)`
139
- **File inputs**: `input[type=file]` (handled separately as FormData)
140
141
### Special Handling
142
143
```javascript
144
// Select elements - includes all selected options
145
<select name="categories" multiple>
146
<option value="1" selected>Tech</option>
147
<option value="2" selected>News</option>
148
</select>
149
// Serializes as: "categories=1&categories=2"
150
151
// Checkbox groups with same name
152
<input type="checkbox" name="tags[]" value="ruby" checked>
153
<input type="checkbox" name="tags[]" value="rails" checked>
154
// Serializes as: "tags%5B%5D=ruby&tags%5B%5D=rails"
155
156
// Submit button information
157
<button type="submit" name="commit" value="publish">Publish</button>
158
// When clicked, adds: "commit=publish"
159
```
160
161
## Form Processing Integration
162
163
### Remote Form Handling
164
165
Forms with `data-remote="true"` use serialization for AJAX submission:
166
167
```html
168
<form action="/posts" method="post" data-remote="true">
169
<input type="text" name="title" value="Hello">
170
<textarea name="body">World</textarea>
171
<button type="submit" name="commit" value="Create">Create Post</button>
172
</form>
173
```
174
175
```javascript
176
// Rails UJS automatically:
177
// 1. Prevents normal form submission
178
// 2. Serializes form data: "title=Hello&body=World&commit=Create"
179
// 3. Makes AJAX request with serialized data
180
// 4. Handles response appropriately
181
```
182
183
### File Upload Handling
184
185
Forms with file inputs use FormData instead of URL encoding:
186
187
```html
188
<form action="/uploads" method="post" enctype="multipart/form-data" data-remote="true">
189
<input type="file" name="document">
190
<input type="text" name="title">
191
<button type="submit">Upload</button>
192
</form>
193
```
194
195
```javascript
196
// Rails UJS detects multipart forms and:
197
// 1. Creates FormData object instead of URL-encoded string
198
// 2. Appends all form fields to FormData
199
// 3. Includes clicked submit button data
200
// 4. Sends as multipart/form-data
201
```
202
203
### Form Method Override
204
205
Rails method override is handled through hidden fields:
206
207
```html
208
<form action="/posts/1" method="post">
209
<input type="hidden" name="_method" value="patch">
210
<input type="text" name="title">
211
</form>
212
```
213
214
The `_method` field is included in serialization to enable REST methods.
215
216
## Element State During Submission
217
218
Form elements are automatically managed during submission:
219
220
```javascript
221
// Before submission:
222
const disableElements = Rails.formElements(form, "[data-disable-with]:enabled");
223
disableElements.forEach(Rails.disableElement);
224
225
// After completion:
226
const enableElements = Rails.formElements(form, "[data-disable-with]:disabled");
227
enableElements.forEach(Rails.enableElement);
228
```
229
230
## Common Selectors
231
232
Rails UJS uses these selectors for form handling:
233
234
```javascript { .api }
235
// Forms that should be processed by Rails UJS
236
const formSubmitSelector = "form:not([data-turbo=true])";
237
238
// Submit buttons and inputs in forms
239
const formInputClickSelector = "form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])";
240
241
// Elements to disable during form submission
242
const formDisableSelector = "input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled";
243
244
// File inputs that need special handling
245
const fileInputSelector = "input[name][type=file]:not([disabled])";
246
```