Implemented dynamic slot name

pull/8535/head
Nguyen Tran 3 years ago
parent 9425f18e52
commit 6787855c52

@ -3,7 +3,7 @@ import Attribute from './Attribute';
import Component from '../Component';
import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
import { TemplateNode } from '../../interfaces';
import { TemplateNode, Attribute as AttributeNode } from '../../interfaces';
import compiler_errors from '../compiler_errors';
export default class Slot extends Element {
@ -11,31 +11,44 @@ export default class Slot extends Element {
name: string;
children: INode[];
slot_name: string;
name_attribute: Attribute;
values: Map<string, Attribute> = new Map();
constructor(component: Component, parent: INode, scope: TemplateScope, info: TemplateNode) {
super(component, parent, scope, info);
info.attributes.forEach(attr => {
info.attributes.forEach((attr: AttributeNode) => {
if (attr.type !== 'Attribute' && attr.type !== 'Spread') {
return component.error(attr, compiler_errors.invalid_slot_directive);
}
const new_attribute = new Attribute(component, this, scope, attr);
if (attr.name === 'name') {
if (attr.value.length !== 1 || attr.value[0].type !== 'Text') {
return component.error(attr, compiler_errors.dynamic_slot_name);
if (attr.value.length === 1 && attr.value[0].type === 'Text') {
this.slot_name = attr.value[0].data;
} else {
this.slot_name = component.get_unique_name('dynamic_slot_name').name;
}
this.slot_name = attr.value[0].data;
if (this.slot_name === 'default') {
return component.error(attr, compiler_errors.invalid_slot_name);
}
this.name_attribute = new_attribute;
}
this.values.set(attr.name, new Attribute(component, this, scope, attr));
this.values.set(attr.name, new_attribute);
});
if (!this.slot_name) this.slot_name = 'default';
if (!this.slot_name) {
// If there is no name attribute, pretend we do have a name attribute with value 'default'
this.slot_name = 'default';
this.name_attribute = new Attribute(component, this, scope, {
type: 'Attribute',
name: 'name',
value: [ { type: 'Text', data: 'default' } ]
} as AttributeNode);
}
if (this.slot_name === 'default') {
// if this is the default slot, add our dependencies to any

@ -69,7 +69,7 @@ export default class SlotWrapper extends Wrapper {
) {
const { renderer } = this;
const { slot_name } = this.node;
const { slot_name, name_attribute } = this.node;
if (this.slot_block) {
block = this.slot_block;
@ -128,8 +128,9 @@ export default class SlotWrapper extends Wrapper {
const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot;
const slot_expression = name_attribute.get_value(block);
block.chunks.init.push(b`
const ${slot_definition} = ${renderer.reference('#slots')}.${slot_name};
const ${slot_definition} = ${renderer.reference('#slots')}[${slot_expression}];
const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn});
${has_fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null}
`);

@ -2,6 +2,7 @@ import Renderer, { RenderOptions } from '../Renderer';
import Slot from '../../nodes/Slot';
import { x } from 'code-red';
import get_slot_data from '../../utils/get_slot_data';
import { get_attribute_value } from './shared/get_attribute_value';
import { get_slot_scope } from './shared/get_slot_scope';
export default function(node: Slot, renderer: Renderer, options: RenderOptions & {
@ -19,9 +20,10 @@ export default function(node: Slot, renderer: Renderer, options: RenderOptions &
renderer.render(node.children, options);
const result = renderer.pop();
const slot_expression = get_attribute_value(node.name_attribute);
renderer.add_expression(x`
#slots.${node.slot_name}
? #slots.${node.slot_name}(${slot_data})
#slots[${slot_expression}]
? #slots[${slot_expression}](${slot_data})
: ${result}
`);

Loading…
Cancel
Save