diff --git a/src/generators/dom/preprocess.ts b/src/generators/dom/preprocess.ts index a6333c286c..1bdedd6795 100644 --- a/src/generators/dom/preprocess.ts +++ b/src/generators/dom/preprocess.ts @@ -256,6 +256,7 @@ const preprocessors = { ) => { cannotUseInnerHTML(node); node.var = block.getUniqueName(`each`); + node.iterations = block.getUniqueName(`${node.var}_blocks`); const { dependencies } = node.metadata; block.addDependencies(dependencies); diff --git a/src/generators/dom/visitors/Component.ts b/src/generators/dom/visitors/Component.ts index eac4fa30aa..0e8cb3d69a 100644 --- a/src/generators/dom/visitors/Component.ts +++ b/src/generators/dom/visitors/Component.ts @@ -7,6 +7,7 @@ import isDomNode from './shared/isDomNode'; import getTailSnippet from '../../../utils/getTailSnippet'; import getObject from '../../../utils/getObject'; import getExpressionPrecedence from '../../../utils/getExpressionPrecedence'; +import getStaticAttributeValue from '../../../utils/getStaticAttributeValue'; import { stringify } from '../../../utils/stringify'; import stringifyProps from '../../../utils/stringifyProps'; import { Node } from '../../../interfaces'; @@ -281,6 +282,8 @@ export default function visitComponent( if (${switch_vars.value}) { ${name} = new ${switch_vars.value}(${switch_vars.props}(${params})); ${name}._fragment.c(); + + ${node.children.map(child => remount(generator, child, name))} ${name}._mount(${anchor}.parentNode, ${anchor}); ${eventHandlers.map(handler => deindent` @@ -554,4 +557,32 @@ function isComputed(node: Node) { } return false; +} + +function remount(generator: DomGenerator, node: Node, name: string) { + // TODO make this a method of the nodes + + if (node.type === 'Element') { + if (node.name === ':Self' || node.name === ':Switch' || generator.components.has(node.name)) { + return `${node.var}._mount(${name}._slotted.default, null);`; + } + + const slot = node.attributes.find(attribute => attribute.name === 'slot'); + if (slot) { + return `@appendNode(${node.var}, ${name}._slotted.${getStaticAttributeValue(node, 'slot')});`; + } + + return `@appendNode(${node.var}, ${name}._slotted.default);`; + } + + if (node.type === 'Text' || node.type === 'MustacheTag' || node.type === 'RawMustacheTag') { + return `@appendNode(${node.var}, ${name}._slotted.default);`; + } + + if (node.type === 'EachBlock') { + // TODO consider keyed blocks + return `for (var #i = 0; #i < ${node.iterations}.length; #i += 1) ${node.iterations}[#i].m(${name}._slotted.default, null);`; + } + + return `${node.var}.m(${name}._slotted.default, null);`; } \ No newline at end of file diff --git a/src/generators/dom/visitors/EachBlock.ts b/src/generators/dom/visitors/EachBlock.ts index fd36e6533d..6b659ccf06 100644 --- a/src/generators/dom/visitors/EachBlock.ts +++ b/src/generators/dom/visitors/EachBlock.ts @@ -18,7 +18,7 @@ export default function visitEachBlock( const create_each_block = node._block.name; const each_block_value = node._block.listName; - const iterations = block.getUniqueName(`${each}_blocks`); + const iterations = node.iterations; const params = block.params.join(', '); const needsAnchor = node.next ? !isDomNode(node.next, generator) : !state.parentNode || !isDomNode(node.parent, generator); diff --git a/src/generators/shared/utils/isChildOfComponent.ts b/src/generators/shared/utils/isChildOfComponent.ts index 2de64c4860..e74b6a658b 100644 --- a/src/generators/shared/utils/isChildOfComponent.ts +++ b/src/generators/shared/utils/isChildOfComponent.ts @@ -4,7 +4,7 @@ import Generator from '../../Generator'; export default function isChildOfComponent(node: Node, generator: Generator) { while (node = node.parent) { if (node.type !== 'Element') continue; - if (generator.components.has(node.name)) return true; + if (node.name === ':Self' || node.name === ':Switch' || generator.components.has(node.name)) return true; // TODO extract this out into a helper if (/-/.test(node.name)) return false; } } \ No newline at end of file diff --git a/src/validate/html/validateElement.ts b/src/validate/html/validateElement.ts index 721a91cb6c..46e6bb94bf 100644 --- a/src/validate/html/validateElement.ts +++ b/src/validate/html/validateElement.ts @@ -230,7 +230,7 @@ function checkSlotAttribute(validator: Validator, node: Node, attribute: Node, s const parent = stack[i]; if (parent.type === 'Element') { // if we're inside a component or a custom element, gravy - if (validator.components.has(parent.name)) return; + if (parent.name === ':Self' || parent.name === ':Switch' || validator.components.has(parent.name)) return; if (/-/.test(parent.name)) return; } diff --git a/test/runtime/samples/dynamic-component-slot/Bar.html b/test/runtime/samples/dynamic-component-slot/Bar.html new file mode 100644 index 0000000000..76cea7cb67 --- /dev/null +++ b/test/runtime/samples/dynamic-component-slot/Bar.html @@ -0,0 +1,3 @@ +
element
+ you're it +neither foo nor bar
+ text + a + b + c +element
+ you're it +neither foo nor bar
+ text + a + b + c +element
+ + {{tag}} + + {{#if foo}} +foo
+ {{elseif bar}} +bar
+ {{else}} +neither foo nor bar
+ {{/if}} + + text + + {{#each things as thing}} + {{thing}} + {{/each}} + +