awsirkis
awsirkis

Reputation: 399

How to use slots inside of template components in HTML

I'm trying to use slots inside of a Vue component to display different titles more easily. However, when I try to replace the slot with data, regardless of the relative positioning in the markup, the slot only uses it's fallback option.

It's my understanding that the template to be used goes first, with a label, then slots are put in and given a "name," with fallback text between the opening and closing slot tags, like so:

<template id="somename-template>
     <slot name="attrname>Some Fallback</slot>
</template>

Then data is stored as such:

<somename>
     <span slot="attrname">Real text</slot>
</somename>

I have tried repositioning the both above and below the script, and above and below the , however no combination provides the expected results.

My actual code:

<body>
    <template id="comp-dem-template">
        <header-component></header-component>
    </template>

    <script>
        customElements.define('comp-dem',

            class extends HTMLElement {

            constructor() {

                super();

                const template = document.getElementById('comp-dem-template').content;

                const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(template.cloneNode(true));

            }

        });
        Vue.component('header-component', {
            template: '<h1><slot name="pagetitle">Page Title Fallback</slot></h1>'
        })
        new Vue({ el: '#comp-dem-template' })
    </script>
    <comp-dem>
        <span slot="pagetitle">
            Images
        </span>
    </comp-dem>
</body>

The markup should look like:

<h1>Images</h1>

However, instead looks like:

<h1>Page Title Fallback</h1>

I can tell it's probably a super simple thing that I'm doing wrong (or it's the wrong tool for the job), but even looking at other working examples, I can't tell what that exactly is.

Upvotes: 1

Views: 1519

Answers (1)

Cathy Ha
Cathy Ha

Reputation: 1677

It's not quite clear to me what you're trying to accomplish. You're passing the <span slot="pagetitle">Images</span> to <comp-dem> but the <comp-dem> component doesn't have a slot - it's the <header-component> that has a slot. Why do you need to wrap a component in a component?

For the code to work, the slot needs to be passed like so:

    <body>
        <template id="comp-dem-template">
            <header-component>
                <span slot="pagetitle">
                    Images
                </span>
            </header-component>
        </template>

        <script>
            Vue.component('header-component', {
                template: '<h1><slot name="pagetitle">Page Title Fallback</slot></h1>'
            })
            new Vue({ el: '#comp-dem-template' })
        </script>
    </body>

Or, if you insist on using <comp-dem>, I think you might need to do the following:

    <body>
        <template id="comp-dem-template">
            <header-component>
                <span slot="pagetitle">
                    <slot name="pagetitle"><slot>
                </span>
            </header-component>
        </template>

        <script>
            customElements.define('comp-dem',

                class extends HTMLElement {

                constructor() {

                    super();

                    const template = document.getElementById('comp-dem-template').content;

                    const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(template.cloneNode(true));

                }

            });
            Vue.component('header-component', {
                template: '<h1><slot name="pagetitle">Page Title Fallback</slot></h1>'
            })
            new Vue({ el: '#comp-dem-template' })
        </script>
        <comp-dem>
            <span slot="pagetitle">
                Images
            </span>
        </comp-dem>
    </body>

Upvotes: 1

Related Questions