Skip to content

define slot

Steve Hannah edited this page Jul 13, 2021 · 1 revision

<define-slot>

Synopsis

Defines a "placeholder" slot in the view that allows controllers or parent views to inject their own content.

Usage

You can define a slot anywhere in your view. The child elements of the <define-slot> element are the default content for the slot, and will be rendered the slot contents are not "replaced" by a controller or parent view.

...
<define-slot id="SLOT_ID">
    <!-- Place default slot contents here -->
</define-slot>
...

There are two ways to replace the slot contents. If you are including this view inside another view, then you can use the <fill-slot> tag in the other view to replace the contents. E.g. Consider the following slot definition in a view named MyView:

MyView.xml
...
<define-slot id="topLeftSlot">
    <label>Default Content</label>
    <spanLabel>This is the default top-left slot contents.</spanLabel>
</define-slot>
...

We then create another view - let’s call it OtherView - and we embed an instance of MyView as follows:

OtherView.xml
...
<myView>
    <fill-slot id="topLeftSlot">
        <label>Replacement Content</label>
        <spanLabel>This is the replacement content of the top-left slot</spanLabel>
    </fill-slot>
</myView>
...

OtherView will display the embedded MyView, but the slot contents will be replaced by the contents of the <fill-slot> tag.

Attributes

id

The ID of the slot. <fill-slot> tags that target this <define-slot> tag should use the same ID.

Examples

In the following example we define a view, DefineSlotSample that includes a <define-slot> tag with id="topLeftSlot". This slot includes some default content. We then define a second view, FillSlotSample that embeds two instances of our DefineSlotSample view via the <defineSlotSample> tag. The first embed doesn’t include anything special and will render the <defineSlotSample> instance with its default content. The second one includes a <fill-slot> tag that provides alternate content to inject into the topLeftSlot slot.

DefineSlotSample.xml
<?xml version="1.0"?>
<border safeArea="true" xsi:noNamespaceSchemaLocation="DefineSlotSample.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <title>Define Slot Sample</title>
    <border layout-constraint="north">
        <define-slot id="topLeftSlot" layout-constraint="west">
            <y>
                <label>Default Content</label>
                <spanLabel>This is the default content of topLeftSlot</spanLabel>
            </y>
        </define-slot>
        <y layout-constraint="center">
            <label>North Area</label>
        </y>
    </border>


    <y layout-constraint="center">
        <spanLabel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</spanLabel>
    </y>
    <button layout-constraint="south">
        South Button
    </button>
</border>
FillSlotSample.xml
<?xml version="1.0"?>
<y safeArea="true" xsi:noNamespaceSchemaLocation="FillSlotSample.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <title>FillSlot Sample</title>

    <spanLabel>DefineSlotSample with default content:</spanLabel>
    <defineSlotSample/>

    <spanLabel>DefineSlotSample with overridden content:</spanLabel>
    <defineSlotSample>
        <fill-slot id="topLeftSlot">
            <label>Overridden</label>
            <spanLabel>This content was overridden in the FillSlotSample template</spanLabel>
        </fill-slot>

    </defineSlotSample>
</y>

The result looks like:

FillSlotSample

Example 2: Filling Slot in Controller

This example demonstrates how you can fill slot content in the controller, rather than the view. Using the same DefineSlotSample view from the previous example, we define a new view and accomanying view controller as follows:

DefineSlotSample2.xml
<?xml version="1.0"?>
<y safeArea="true" view-controller="com.codename1.rad.sampler.controllers.DefineSlotSample2ViewController" xsi:noNamespaceSchemaLocation="DefineSlotSample2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <title>FillSlot From Controller</title>


    <!-- The topLeftSlot of the DefineSlotSample component will be filled
        by the DefineSlotSample2ViewController because it includes a fillSlot() hook -->
    <defineSlotSample/>


</y>
DefineSlotSample2ViewController.java
package com.codename1.rad.sampler.controllers;

import com.codename1.components.SpanLabel;
import com.codename1.rad.controllers.Controller;
import com.codename1.rad.controllers.ViewController;
import com.codename1.rad.sampler.DefineSlotSample;

public class DefineSlotSample2ViewController extends ViewController {
    /**
     * Creates a new ViewController with the given parent controller.
     *
     * @param parent
     */
    public DefineSlotSample2ViewController(Controller parent) {
        super(parent);
    }

    @Override
    protected void onStartController() {
        super.onStartController();
        fillSlot(DefineSlotSample.topLeftSlot, evt -> { (1)
            evt.consume(); (2)
            evt.getSlot().setContent(new SpanLabel("This content was replaced in DefineSlotSample2ViewController")); (3)
        });
    }
}
  1. We call fillSlot() with the topLeftSlot tag (which is automatically generated on the DefineSlotSample view java class) to add a callback that will allow us to "fill" the slot when the view is "activated".

  2. evt.consume() will prevent that fill slot event from propagating up to other controllers in the hierarchy. If you don’t consume this event, then it is possible that a parent controller like the application controller could re-fill the contents with its own.

  3. evt.getSlot().setContent(…​). We get the slot reference from the event, and set its content using the setContent() method.

And the result:

DefineSlotSample2

See Also

Clone this wiki locally