slotted contents of dynamic components

pull/971/head
Rich Harris 8 years ago
parent f4e66c0e72
commit e6ef5af6ba

@ -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);

@ -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`
@ -555,3 +558,31 @@ 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);`;
}

@ -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);

@ -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;
}
}

@ -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;
}

@ -0,0 +1,3 @@
<h1>Bar</h1>
<slot></slot>
<slot name='other'></slot>

@ -0,0 +1,3 @@
<h1>Foo</h1>
<slot name='other'></slot>
<slot></slot>

@ -0,0 +1,37 @@
export default {
data: {
x: true
},
html: `
<h1>Foo</h1>
<div slot='other'>what goes up must come down</div>
<p>element</p>
you're it
<p>neither foo nor bar</p>
text
<span>a</span>
<span>b</span>
<span>c</span>
<div>baz</div>
`,
test(assert, component, target) {
component.set({
x: false
});
assert.htmlEqual(target.innerHTML, `
<h1>Bar</h1>
<p>element</p>
you're it
<p>neither foo nor bar</p>
text
<span>a</span>
<span>b</span>
<span>c</span>
<div>baz</div>
<div slot='other'>what goes up must come down</div>
`);
}
};

@ -0,0 +1,45 @@
<:Switch { x ? Foo : Bar } x='{{x}}'>
<p>element</p>
{{tag}}
{{#if foo}}
<p>foo</p>
{{elseif bar}}
<p>bar</p>
{{else}}
<p>neither foo nor bar</p>
{{/if}}
text
{{#each things as thing}}
<span>{{thing}}</span>
{{/each}}
<Baz/>
<div slot='other'>what goes up must come down</div>
</:Switch>
<script>
import Foo from './Foo.html';
import Bar from './Bar.html';
import Baz from './Baz.html';
export default {
data() {
return {
Foo,
Bar,
tag: 'you\'re it',
things: ['a', 'b', 'c']
};
},
components: {
Baz
}
};
</script>
Loading…
Cancel
Save