Skip to content

Commit 4bf01b7

Browse files
[Live] Preserve file input values after render requests
1 parent 31fd264 commit 4bf01b7

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

src/LiveComponent/assets/dist/live_controller.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,9 +2120,6 @@ class Component {
21202120
this.backendRequest.promise.then(async (response) => {
21212121
const backendResponse = new BackendResponse(response);
21222122
const html = await backendResponse.getBody();
2123-
for (const input of Object.values(this.pendingFiles)) {
2124-
input.value = '';
2125-
}
21262123
const headers = backendResponse.response.headers;
21272124
if (!headers.get('Content-Type')?.includes('application/vnd.live-component+html') &&
21282125
!headers.get('X-Live-Redirect')) {

src/LiveComponent/assets/src/Component/index.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,6 @@ export default class Component {
302302
const backendResponse = new BackendResponse(response);
303303
const html = await backendResponse.getBody();
304304

305-
// clear sent files inputs
306-
for (const input of Object.values(this.pendingFiles)) {
307-
input.value = '';
308-
}
309-
310305
// if the response does not contain a component, render as an error
311306
const headers = backendResponse.response.headers;
312307
if (

src/LiveComponent/assets/test/controller/render.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,45 @@ describe('LiveController rendering Tests', () => {
109109
expect((test.queryByDataModel('comment') as HTMLTextAreaElement).value).toEqual('I HAD A GREAT TIME');
110110
});
111111

112+
it('keeps file input value after a render request', async () => {
113+
const test = await createTest(
114+
{},
115+
() => `
116+
<div ${initComponent({}, { debounce: 1 })}>
117+
<input type="file" data-model="file">
118+
<button data-action="live#$render">Reload</button>
119+
</div>
120+
`
121+
);
122+
123+
const fileInput = test.element.querySelector('input[type="file"]') as HTMLInputElement;
124+
const file = new File(['content'], 'test.txt', { type: 'text/plain' });
125+
126+
Object.defineProperty(fileInput, 'files', {
127+
value: [file],
128+
writable: false,
129+
});
130+
131+
// Checks that the file is correctly assigned before rendering
132+
expect(fileInput.files).not.toBeNull();
133+
expect(fileInput.files?.length).toBe(1);
134+
expect(fileInput.files?.[0].name).toBe('test.txt');
135+
136+
// Simulates an AJAX request triggered by Live rendering
137+
test.expectsAjaxCall()
138+
.expectUpdatedData({})
139+
.delayResponse(100);
140+
141+
getByText(test.element, 'Reload').click();
142+
143+
// Checks that the file is still present after rendering
144+
await waitFor(() => {
145+
expect(fileInput.files).not.toBeNull();
146+
expect(fileInput.files?.length).toBe(1);
147+
expect(fileInput.files?.[0].name).toBe('test.txt');
148+
});
149+
});
150+
112151
it('conserves the value of an unmapped field that was modified after a render request', async () => {
113152
const test = await createTest(
114153
{ title: 'greetings' },

0 commit comments

Comments
 (0)