Using Slots in Polymer Templates
Note | Use Lit templates instead Lit templates are recommended. Polymer templates are available in the next long term supported Vaadin version (LTS), but they are deprecated. |
A Polymer template cannot render child templates created using the Component
or Element
API, because PolymerTemplate
uses the shadow DOM that renders the shadow tree, instead of the element’s children that are in the light DOM.
To overcome this, you can add a <slot>
element to mark the place where the light DOM elements should be rendered.
Example: <slot>
element in a JavaScript Polymer template.
js
import {PolymerElement,html} from '@polymer/polymer/polymer-element.js';
class ComponentContainer extends PolymerElement {
static get template() {
return html`
<div>
<slot></slot>
</div>`;
}
static get is() {
return 'component-container';
}
}
customElements.define(ComponentContainer.is, ComponentContainer);
Example: Mapped Java template class.
Java
@Tag("component-container")
@JsModule("./com/example/component-container.js")
public class ComponentContainer extends PolymerTemplate<TemplateModel> {
public ComponentContainer() {
Element label = ElementFactory.createLabel("Main layout header");
Element button = ElementFactory.createButton("Click me");
getElement().appendChild(label, button);
}
}
Without the
<slot>
tag in the JavaScript template, thelabel
andbutton
would not be visible to the user, even though they can be located in the DOM.You can add multiple components that will display in the slot when added to a template element with an open
<slot></slot>
.
Note | You can remove any element from a <slot> . It will work as expected and no longer display in the main element. |
Using Default Content in the <slot> Element
The <slot>
tag can contain default content that is displayed only if nothing else is set from the light DOM.
Example: <slot>
element with default content in a JavaScript Polymer template.
js
<div style="border: 1px solid black; padding: 10px; margin: 10px;">
<slot>No components added</slot>
</div>
- ‘No components added’ displays initially, and is replaced when at least one child element is added.
Naming <slot> Elements
You can name <slot>
elements using the name
attribute to ensure that only wanted content is added to a particular slot.
Example Using the name
attribute in the <slot>
element in a JavaScript Polymer template.
js
<h1><slot name="title"></slot></h1>
<div style="border: 1px solid black; margin: 5px;padding: 5px;">
<slot>No content given!</slot>
</div>
- A
<label slot="title">Main header</label>
element, for example, will now NOT be positioned in the default “No content given!” slot, but rather in the<h1><slot name="title">…
slot.
Nesting <slot> Elements
You can also nest named slots inside the main slot.
Example: Nested slot elements in a JavaScript Polymer template.
js
<slot name="fullName">
<slot name="firstName"></slot>, <slot name="lastName"></slot>
</slot>
- The slot shows data for the light DOM
<slot="firstName">
and<slot="lastName">
elements, if no<slot="fullName">
element is available. If you add an element to the<slot="fullName">
slot, it overrides and replaces thefirstName and lastName
data.
Adding Multiple <slot> Elements
The default slot and any named slot can contain multiple elements.
Example: Defining multiple elements for the default slot and multiple named slots.
Java
@Tag("name-element")
@JsModule("./com/example/name-element.js")
public class NameElement extends PolymerTemplate<TemplateModel> {
public NameElement() {
Element firstName = ElementFactory.createSpan("Jack");
Element middleName = ElementFactory.createSpan(" James");
Element surName = ElementFactory.createSpan("Christobald");
firstName.setAttribute("slot", "firstName");
middleName.setAttribute("slot", "middleName");
surName.setAttribute("slot", "lastName");
getElement().appendChild(firstName, middleName, surName);
}
}
Using a PolymerTemplate as a Parent Layout
A PolymerTemplate
can be used as a parent layout, by using the <slot>
in the position where the child view should be displayed.
Example: JavaScript Polymer template showing the actual view, MainLayout
, below a heading and menu.
js
import {PolymerElement,html} from '@polymer/polymer/polymer-element.js';
class MainLayout extends PolymerElement {
static get template() {
return html`
<h1>Site title</h1>
<div class="menu">...</div>
<!-- child content comes here -->
<slot></slot>
`;
}
static get is() {
return 'main-layout'
}
}
customElements.define(MainLayout.is, MainLayout);
To use this template file, you need a basic Java template class that is mapped to the JavaScript template file (using the @JsModule
annotation) and that implements the RouterLayout
interface.
Example: Mapped Java template class that imports the JavaScript template and implements RouterLayout
.
Java
@Tag("main-layout")
@JsModule("./com/example/main-layout.js")
public class MainLayout extends PolymerTemplate<TemplateModel>
implements RouterLayout {
}
- The
showRouterLayoutContent(HasElement)
method in theRouterLayout
interface has a default implementation. This makes it unnecessary to write additional code, but you can override and re-implement it, if necessary.
You can now use MainLayout
as a parent layout using the @Route
or @ParentLayout
annotations.
Example: Using the layout
parameter in the @Route
annotation to mark MainLayout
as the parent layout.
Java
@Route(value="editor", layout=MainLayout.class)
public class Editor extends Div {
}
@ParentLayout(MainLayout.class)
public class MenuBar extends Div {
}
See the following resources for related information:
Router Layouts and Nested Router Targets for more about parent views.
Creating A Simple Component Using the PolymerTemplate API for general information about the
PolymerTemplate
API.