Skip to content

Commit 2572f0b

Browse files
committed
allow setting files binding
1 parent 3173fdd commit 2572f0b

File tree

5 files changed

+29
-6
lines changed

5 files changed

+29
-6
lines changed

documentation/docs/02-template-syntax/05-element-directives.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Numeric input values are coerced; even though `input.value` is a string as far a
121121
<input type="range" bind:value={num} />
122122
```
123123

124-
On `<input>` elements with `type="file"`, you can use `bind:files` to get the [`FileList` of selected files](https://developer.mozilla.org/en-US/docs/Web/API/FileList). It is readonly.
124+
On `<input>` elements with `type="file"`, you can use `bind:files` to get the [`FileList` of selected files](https://developer.mozilla.org/en-US/docs/Web/API/FileList).
125125

126126
```svelte
127127
<label for="avatar">Upload a picture:</label>

packages/svelte/src/compiler/compile/nodes/Binding.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,12 @@ export default class Binding extends Node {
9494
return;
9595
}
9696
}
97-
const type = parent.get_static_attribute_value('type');
9897
this.is_readonly =
9998
regex_dimensions.test(this.name) ||
10099
regex_box_size.test(this.name) ||
101100
(isElement(parent) &&
102-
((parent.is_media_node() && read_only_media_attributes.has(this.name)) ||
103-
(parent.name === 'input' && type === 'file'))) /* TODO others? */;
101+
parent.is_media_node() &&
102+
read_only_media_attributes.has(this.name)) /* TODO others? */;
104103
}
105104
is_readonly_media_attribute() {
106105
return read_only_media_attributes.has(this.name);

packages/svelte/src/compiler/compile/render_ssr/handlers/Element.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,15 @@ export default function (node, renderer, options) {
176176
node_contents = x`@escape(${snippet} || "")`;
177177
} else if (binding.name === 'value' && node.name === 'select') {
178178
// NOTE: do not add "value" attribute on <select />
179+
} else if (
180+
binding.name === 'value' &&
181+
node.name === 'input' &&
182+
node.get_static_attribute_value('type') === 'file'
183+
) {
184+
const value = node.get_static_attribute_value('value');
185+
if (value !== '') {
186+
// NOTE: do not add "value" attribute on <input type="file" />
187+
}
179188
} else {
180189
const snippet = expression.node;
181190
renderer.add_expression(

packages/svelte/test/js/samples/bindings-readonly-order/expected.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ function create_fragment(ctx) {
3030
},
3131
m(target, anchor) {
3232
insert(target, input0, anchor);
33+
input0.files = /*files*/ ctx[0];
3334
insert(target, t, anchor);
3435
insert(target, input1, anchor);
36+
input1.files = /*files*/ ctx[0];
3537

3638
if (!mounted) {
3739
dispose = [
@@ -42,7 +44,15 @@ function create_fragment(ctx) {
4244
mounted = true;
4345
}
4446
},
45-
p: noop,
47+
p(ctx, [dirty]) {
48+
if (dirty & /*files*/ 1) {
49+
input0.files = /*files*/ ctx[0];
50+
}
51+
52+
if (dirty & /*files*/ 1) {
53+
input1.files = /*files*/ ctx[0];
54+
}
55+
},
4656
i: noop,
4757
o: noop,
4858
d(detaching) {

packages/svelte/test/js/samples/input-files/expected.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,18 @@ function create_fragment(ctx) {
2424
},
2525
m(target, anchor) {
2626
insert(target, input, anchor);
27+
input.files = /*files*/ ctx[0];
2728

2829
if (!mounted) {
2930
dispose = listen(input, "change", /*input_change_handler*/ ctx[1]);
3031
mounted = true;
3132
}
3233
},
33-
p: noop,
34+
p(ctx, [dirty]) {
35+
if (dirty & /*files*/ 1) {
36+
input.files = /*files*/ ctx[0];
37+
}
38+
},
3439
i: noop,
3540
o: noop,
3641
d(detaching) {

0 commit comments

Comments
 (0)