feat: ssr select value

pull/16017/head
paoloricciuti 4 months ago
parent 94a2bca0e3
commit 6af745e781

@ -7,7 +7,7 @@ import { dev, locator } from '../../../../state.js';
import * as b from '#compiler/builders'; import * as b from '#compiler/builders';
import { clean_nodes, determine_namespace_for_children } from '../../utils.js'; import { clean_nodes, determine_namespace_for_children } from '../../utils.js';
import { build_element_attributes } from './shared/element.js'; import { build_element_attributes } from './shared/element.js';
import { process_children, build_template } from './shared/utils.js'; import { process_children, build_template, build_attribute_value } from './shared/utils.js';
/** /**
* @param {AST.RegularElement} node * @param {AST.RegularElement} node
@ -71,6 +71,42 @@ export function RegularElement(node, context) {
); );
} }
let select_with_value = false;
if (node.name === 'select') {
const value = node.attributes.find(
(attribute) =>
((attribute.type === 'Attribute' || attribute.type === 'BindDirective') &&
attribute.name === 'value') ||
attribute.type === 'SpreadAttribute'
);
if (value) {
select_with_value = true;
const left = b.id('$$payload.select_value');
if (value.type === 'SpreadAttribute') {
state.template.push(
b.stmt(b.assignment('=', left, b.member(value.expression, 'value', false, true)))
);
} else if (value.type === 'Attribute') {
state.template.push(
b.stmt(b.assignment('=', left, build_attribute_value(value.value, context)))
);
} else if (value.type === 'BindDirective') {
state.template.push(
b.stmt(
b.assignment(
'=',
left,
value.expression.type === 'SequenceExpression'
? b.call(value.expression.expressions[0])
: value.expression
)
)
);
}
}
}
if (body === null) { if (body === null) {
process_children(trimmed, { ...context, state }); process_children(trimmed, { ...context, state });
} else { } else {
@ -96,6 +132,10 @@ export function RegularElement(node, context) {
); );
} }
if (select_with_value) {
state.template.push(b.stmt(b.assignment('=', b.id('$$payload.select_value'), b.void0)));
}
if (!node_is_void) { if (!node_is_void) {
state.template.push(b.literal(`</${node.name}>`)); state.template.push(b.literal(`</${node.name}>`));
} }

@ -236,6 +236,16 @@ export function build_element_attributes(node, context) {
); );
} }
if (node.name === 'option' && name === 'value') {
context.state.template.push(
b.call(
'$.maybe_selected',
b.id('$$payload'),
literal_value != null ? b.literal(/** @type {any} */ (literal_value)) : b.void0
)
);
}
continue; continue;
} }
@ -260,6 +270,10 @@ export function build_element_attributes(node, context) {
b.call('$.attr', b.literal(name), value, is_boolean_attribute(name) && b.true) b.call('$.attr', b.literal(name), value, is_boolean_attribute(name) && b.true)
); );
} }
if (name === 'value' && node.name === 'option') {
context.state.template.push(b.call('$.maybe_selected', b.id('$$payload'), value));
}
} }
} }

@ -535,3 +535,12 @@ export function derived(fn) {
return updated_value; return updated_value;
}; };
} }
/**
*
* @param {Payload} payload
* @param {*} value
*/
export function maybe_selected(payload, value) {
return value === payload.select_value ? ' selected' : '';
}

@ -18,6 +18,7 @@ export class Payload {
css = new Set(); css = new Set();
out = ''; out = '';
uid = () => ''; uid = () => '';
select_value = undefined;
head = new HeadPayload(); head = new HeadPayload();

@ -4,7 +4,7 @@ import { ok, test } from '../../test';
export default test({ export default test({
html: ` html: `
<select> <select>
<option value="a">A</option> <option selected="" value="a">A</option>
<option value="b">B</option> <option value="b">B</option>
</select> </select>
selected: a selected: a

@ -0,0 +1 @@
<select><option value="">--Please choose an option--</option><option value="dog" selected>Dog</option><option value="cat">Cat</option></select>

@ -0,0 +1,5 @@
<select value="dog">
<option value="">--Please choose an option--</option>
<option value="dog">Dog</option>
<option value="cat">Cat</option>
</select>

@ -3,5 +3,5 @@ import * as $ from 'svelte/internal/server';
export default function Skip_static_subtree($$payload, $$props) { export default function Skip_static_subtree($$payload, $$props) {
let { title, content } = $$props; let { title, content } = $$props;
$$payload.out += `<header><nav><a href="/">Home</a> <a href="/away">Away</a></nav></header> <main><h1>${$.escape(title)}</h1> <div class="static"><p>we don't need to traverse these nodes</p></div> <p>or</p> <p>these</p> <p>ones</p> ${$.html(content)} <p>these</p> <p>trailing</p> <p>nodes</p> <p>can</p> <p>be</p> <p>completely</p> <p>ignored</p></main> <cant-skip><custom-elements with="attributes"></custom-elements></cant-skip> <div><input autofocus/></div> <div><source muted/></div> <select><option value="a">a</option></select> <img src="..." alt="" loading="lazy"/> <div><img src="..." alt="" loading="lazy"/></div>`; $$payload.out += `<header><nav><a href="/">Home</a> <a href="/away">Away</a></nav></header> <main><h1>${$.escape(title)}</h1> <div class="static"><p>we don't need to traverse these nodes</p></div> <p>or</p> <p>these</p> <p>ones</p> ${$.html(content)} <p>these</p> <p>trailing</p> <p>nodes</p> <p>can</p> <p>be</p> <p>completely</p> <p>ignored</p></main> <cant-skip><custom-elements with="attributes"></custom-elements></cant-skip> <div><input autofocus/></div> <div><source muted/></div> <select><option value="a"${$.maybe_selected($$payload, 'a')}>a</option></select> <img src="..." alt="" loading="lazy"/> <div><img src="..." alt="" loading="lazy"/></div>`;
} }
Loading…
Cancel
Save