diff --git a/compiler/generate/index.js b/compiler/generate/index.js index 82b38b187a..841f87f17b 100644 --- a/compiler/generate/index.js +++ b/compiler/generate/index.js @@ -133,25 +133,65 @@ export default function generate ( parsed, template ) { } } - else if ( attribute.value.length === 1 && attribute.value[0].type === 'Text' ) { - // static attributes - const value = JSON.stringify( attribute.value[0].data ); + else if ( attribute.value.length === 1 ) { + const value = attribute.value[0]; + + let result = ''; + + if ( value.type === 'Text' ) { + // static attributes + result = JSON.stringify( value.data ); + + if ( metadata ) { + initStatements.push( deindent` + ${name}.${metadata.propertyName} = ${result}; + ` ); + } else { + initStatements.push( deindent` + ${name}.setAttribute( '${attribute.name}', ${result} ); + ` ); + } + } + + else { + // dynamic – but potentially non-string – attributes + contextualise( value.expression ); + result = `[✂${value.expression.start}-${value.expression.end}✂]`; + + if ( metadata ) { + updateStatements.push( deindent` + ${name}.${metadata.propertyName} = ${result}; + ` ); + } else { + updateStatements.push( deindent` + ${name}.setAttribute( '${attribute.name}', ${result} ); + ` ); + } + } + } + + else { + const value = ( attribute.value[0].type === 'Text' ? '' : `"" + ` ) + ( + attribute.value.map( chunk => { + if ( chunk.type === 'Text' ) { + return JSON.stringify( chunk.data ); + } else { + contextualise( code, chunk.expression, current.contexts ); + return `[✂${chunk.expression.start}-${chunk.expression.end}✂]`; + } + }).join( ' + ' ) + ); if ( metadata ) { - initStatements.push( deindent` + updateStatements.push( deindent` ${name}.${metadata.propertyName} = ${value}; ` ); } else { - initStatements.push( deindent` + updateStatements.push( deindent` ${name}.setAttribute( '${attribute.name}', ${value} ); ` ); } } - - else { - // need to handle boolean and string attributes differently - throw new Error( 'TODO dynamic attributes' ); - } } else if ( attribute.type === 'EventHandler' ) { diff --git a/test/compiler/attribute-dynamic/_config.js b/test/compiler/attribute-dynamic/_config.js new file mode 100644 index 0000000000..e9738d114e --- /dev/null +++ b/test/compiler/attribute-dynamic/_config.js @@ -0,0 +1,14 @@ +import * as assert from 'assert'; + +export default { + html: `
red
`, + test ( component, target ) { + const div = target.querySelector( 'div' ); + + assert.equal( div.style.color, 'red' ); + + component.set({ color: 'blue' }); + assert.equal( target.innerHTML, `
blue
` ); + assert.equal( div.style.color, 'blue' ); + } +}; diff --git a/test/compiler/attribute-dynamic/main.svelte b/test/compiler/attribute-dynamic/main.svelte new file mode 100644 index 0000000000..aa743b0cc1 --- /dev/null +++ b/test/compiler/attribute-dynamic/main.svelte @@ -0,0 +1,9 @@ +
{{color}}
+ +