Skip to content

Commit 6af745e

Browse files
committed
feat: ssr select value
1 parent 94a2bca commit 6af745e

File tree

8 files changed

+73
-3
lines changed

8 files changed

+73
-3
lines changed

packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { dev, locator } from '../../../../state.js';
77
import * as b from '#compiler/builders';
88
import { clean_nodes, determine_namespace_for_children } from '../../utils.js';
99
import { build_element_attributes } from './shared/element.js';
10-
import { process_children, build_template } from './shared/utils.js';
10+
import { process_children, build_template, build_attribute_value } from './shared/utils.js';
1111

1212
/**
1313
* @param {AST.RegularElement} node
@@ -71,6 +71,42 @@ export function RegularElement(node, context) {
7171
);
7272
}
7373

74+
let select_with_value = false;
75+
76+
if (node.name === 'select') {
77+
const value = node.attributes.find(
78+
(attribute) =>
79+
((attribute.type === 'Attribute' || attribute.type === 'BindDirective') &&
80+
attribute.name === 'value') ||
81+
attribute.type === 'SpreadAttribute'
82+
);
83+
if (value) {
84+
select_with_value = true;
85+
const left = b.id('$$payload.select_value');
86+
if (value.type === 'SpreadAttribute') {
87+
state.template.push(
88+
b.stmt(b.assignment('=', left, b.member(value.expression, 'value', false, true)))
89+
);
90+
} else if (value.type === 'Attribute') {
91+
state.template.push(
92+
b.stmt(b.assignment('=', left, build_attribute_value(value.value, context)))
93+
);
94+
} else if (value.type === 'BindDirective') {
95+
state.template.push(
96+
b.stmt(
97+
b.assignment(
98+
'=',
99+
left,
100+
value.expression.type === 'SequenceExpression'
101+
? b.call(value.expression.expressions[0])
102+
: value.expression
103+
)
104+
)
105+
);
106+
}
107+
}
108+
}
109+
74110
if (body === null) {
75111
process_children(trimmed, { ...context, state });
76112
} else {
@@ -96,6 +132,10 @@ export function RegularElement(node, context) {
96132
);
97133
}
98134

135+
if (select_with_value) {
136+
state.template.push(b.stmt(b.assignment('=', b.id('$$payload.select_value'), b.void0)));
137+
}
138+
99139
if (!node_is_void) {
100140
state.template.push(b.literal(`</${node.name}>`));
101141
}

packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,16 @@ export function build_element_attributes(node, context) {
236236
);
237237
}
238238

239+
if (node.name === 'option' && name === 'value') {
240+
context.state.template.push(
241+
b.call(
242+
'$.maybe_selected',
243+
b.id('$$payload'),
244+
literal_value != null ? b.literal(/** @type {any} */ (literal_value)) : b.void0
245+
)
246+
);
247+
}
248+
239249
continue;
240250
}
241251

@@ -260,6 +270,10 @@ export function build_element_attributes(node, context) {
260270
b.call('$.attr', b.literal(name), value, is_boolean_attribute(name) && b.true)
261271
);
262272
}
273+
274+
if (name === 'value' && node.name === 'option') {
275+
context.state.template.push(b.call('$.maybe_selected', b.id('$$payload'), value));
276+
}
263277
}
264278
}
265279

packages/svelte/src/internal/server/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,12 @@ export function derived(fn) {
535535
return updated_value;
536536
};
537537
}
538+
539+
/**
540+
*
541+
* @param {Payload} payload
542+
* @param {*} value
543+
*/
544+
export function maybe_selected(payload, value) {
545+
return value === payload.select_value ? ' selected' : '';
546+
}

packages/svelte/src/internal/server/payload.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export class Payload {
1818
css = new Set();
1919
out = '';
2020
uid = () => '';
21+
select_value = undefined;
2122

2223
head = new HeadPayload();
2324

packages/svelte/tests/runtime-legacy/samples/select-in-each/_config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ok, test } from '../../test';
44
export default test({
55
html: `
66
<select>
7-
<option value="a">A</option>
7+
<option selected="" value="a">A</option>
88
<option value="b">B</option>
99
</select>
1010
selected: a
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<select><option value="">--Please choose an option--</option><option value="dog" selected>Dog</option><option value="cat">Cat</option></select>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<select value="dog">
2+
<option value="">--Please choose an option--</option>
3+
<option value="dog">Dog</option>
4+
<option value="cat">Cat</option>
5+
</select>

packages/svelte/tests/snapshot/samples/skip-static-subtree/_expected/server/index.svelte.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)