diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 9b14d1cd6c9b..9d3f60ac7e7c 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -548,6 +548,13 @@ export default class ElementWrapper extends Wrapper { } add_attributes(block: Block) { + // Get all the class dependencies first + this.attributes.forEach((attribute) => { + if (attribute.node.name === 'class' && attribute.node.is_dynamic) { + this.class_dependencies.push(...attribute.node.dependencies); + } + }); + // @ts-ignore todo: if (this.node.attributes.find(attr => attr.type === 'Spread')) { this.add_spread_attributes(block); @@ -555,9 +562,6 @@ export default class ElementWrapper extends Wrapper { } this.attributes.forEach((attribute) => { - if (attribute.node.name === 'class' && attribute.node.is_dynamic) { - this.class_dependencies.push(...attribute.node.dependencies); - } attribute.render(block); }); } diff --git a/src/compiler/compile/render_ssr/handlers/Element.ts b/src/compiler/compile/render_ssr/handlers/Element.ts index 27cf858f1ff9..0cd101df7218 100644 --- a/src/compiler/compile/render_ssr/handlers/Element.ts +++ b/src/compiler/compile/render_ssr/handlers/Element.ts @@ -109,6 +109,9 @@ export default function(node: Element, renderer: Renderer, options: RenderOption ) { // a boolean attribute with one non-Text chunk args.push(`{ ${quote_name_if_necessary(attribute.name)}: ${snip(attribute.chunks[0])} }`); + } else if (attribute.name === 'class' && class_expression) { + // Add class expression + args.push(`{ ${quote_name_if_necessary(attribute.name)}: [\`${stringify_attribute(attribute, true)}\`, \`\${${class_expression}}\`].join(' ').trim() }`); } else { args.push(`{ ${quote_name_if_necessary(attribute.name)}: \`${stringify_attribute(attribute, true)}\` }`); } diff --git a/test/runtime/samples/class-with-dynamic-attribute-and-spread/_config.js b/test/runtime/samples/class-with-dynamic-attribute-and-spread/_config.js new file mode 100644 index 000000000000..58ccc764975b --- /dev/null +++ b/test/runtime/samples/class-with-dynamic-attribute-and-spread/_config.js @@ -0,0 +1,21 @@ +export default { + props: { + myClass: 'one two', + attributes: { + role: 'button' + } + }, + + html: `
`, + + test({ assert, component, target, window }) { + component.myClass = 'one'; + component.attributes = { + 'aria-label': 'Test' + }; + + assert.htmlEqual(target.innerHTML, ` + + `); + } +}; diff --git a/test/runtime/samples/class-with-dynamic-attribute-and-spread/main.svelte b/test/runtime/samples/class-with-dynamic-attribute-and-spread/main.svelte new file mode 100644 index 000000000000..95825c777bed --- /dev/null +++ b/test/runtime/samples/class-with-dynamic-attribute-and-spread/main.svelte @@ -0,0 +1,6 @@ + + + diff --git a/test/runtime/samples/class-with-spread/_config.js b/test/runtime/samples/class-with-spread/_config.js new file mode 100644 index 000000000000..d5233a584969 --- /dev/null +++ b/test/runtime/samples/class-with-spread/_config.js @@ -0,0 +1,21 @@ +export default { + props: { + myClass: 'one two', + attributes: { + role: 'button' + } + }, + + html: ``, + + test({ assert, component, target, window }) { + component.myClass = 'one'; + component.attributes = { + 'aria-label': 'Test' + }; + + assert.htmlEqual(target.innerHTML, ` + + `); + } +}; diff --git a/test/runtime/samples/class-with-spread/main.svelte b/test/runtime/samples/class-with-spread/main.svelte new file mode 100644 index 000000000000..54d8088581c5 --- /dev/null +++ b/test/runtime/samples/class-with-spread/main.svelte @@ -0,0 +1,6 @@ + + +