From 4ec85bb8cc9926c2b2fc198a1b474d6f4110af67 Mon Sep 17 00:00:00 2001 From: Jacob Wright Date: Sat, 25 Aug 2018 14:26:27 -0600 Subject: [PATCH] Adds class directive shortcut When no expression is used in a class directive the class name will be used to evaluate whether the class should be added/removed. E.g. the following will add the class "active" when you call `component.set({ active });`. ```html
``` --- src/compile/nodes/Element.ts | 28 +++++++++++++++---- .../runtime/samples/class-shortcut/_config.js | 16 +++++++++++ test/runtime/samples/class-shortcut/main.html | 1 + 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 test/runtime/samples/class-shortcut/_config.js create mode 100644 test/runtime/samples/class-shortcut/main.html diff --git a/src/compile/nodes/Element.ts b/src/compile/nodes/Element.ts index bee1103dc0..03ee575ecf 100644 --- a/src/compile/nodes/Element.ts +++ b/src/compile/nodes/Element.ts @@ -855,8 +855,8 @@ export default class Element extends Node { const { expression } = action; let snippet, dependencies; if (expression) { - snippet = action.expression.snippet; - dependencies = action.expression.dependencies; + snippet = expression.snippet; + dependencies = expression.dependencies; } const name = block.getUniqueName( @@ -889,7 +889,16 @@ export default class Element extends Node { addClasses(block: Block) { this.classes.forEach(classDir => { - const { expression: { snippet, dependencies}, name } = classDir; + const { expression, name } = classDir; + let snippet, dependencies; + if (expression) { + snippet = expression.snippet; + dependencies = expression.dependencies; + } else { + const varName = camelCase(name); + snippet = `ctx.${varName}`; + dependencies = [varName]; + } const updater = `@toggleClass(${this.var}, "${name}", ${snippet});`; block.builders.hydrate.addLine(updater); @@ -978,7 +987,8 @@ export default class Element extends Node { } const classExpr = this.classes.map((classDir: Class) => { - const { expression: { snippet }, name } = classDir; + const { expression, name } = classDir; + const snippet = expression ? expression.snippet : `ctx.${camelCase(name)}`; return `${snippet} ? "${name}" : ""`; }).join(', '); @@ -1026,7 +1036,7 @@ export default class Element extends Node { openingTag += '${' + attribute.chunks[0].snippet + ' ? " ' + attribute.name + '" : "" }'; } else if (attribute.name === 'class' && classExpr) { addClassAttribute = false; - openingTag += ` class="\${ [\`${attribute.stringifyForSsr()}\`, ${classExpr} ].join(' ') }"`; + openingTag += ` class="\${ [\`${attribute.stringifyForSsr()}\`, ${classExpr} ].join(' ').trim() }"`; } else { openingTag += ` ${attribute.name}="${attribute.stringifyForSsr()}"`; } @@ -1034,7 +1044,7 @@ export default class Element extends Node { } if (addClassAttribute) { - openingTag += ` class="\${ [${classExpr}].join(' ') }"`; + openingTag += ` class="\${ [${classExpr}].join(' ').trim() }"`; } openingTag += '>'; @@ -1159,3 +1169,9 @@ const events = [ name === 'volume' } ]; + +function camelCase(str) { + return str.replace(/(-\w)/g, function (m) { + return m[1].toUpperCase(); + }); +} \ No newline at end of file diff --git a/test/runtime/samples/class-shortcut/_config.js b/test/runtime/samples/class-shortcut/_config.js new file mode 100644 index 0000000000..0d4cfc886d --- /dev/null +++ b/test/runtime/samples/class-shortcut/_config.js @@ -0,0 +1,16 @@ +export default { + data: { + isActive: true, + isSelected: true, + myClass: 'one two' + }, + html: `
`, + + test ( assert, component, target, window ) { + component.set({ isActive: false }); + + assert.htmlEqual( target.innerHTML, ` +
+ ` ); + } +}; diff --git a/test/runtime/samples/class-shortcut/main.html b/test/runtime/samples/class-shortcut/main.html new file mode 100644 index 0000000000..8e608c33e7 --- /dev/null +++ b/test/runtime/samples/class-shortcut/main.html @@ -0,0 +1 @@ +