mtelligent

View Original

Building your own SXA Composite components

The SXA Toolbox has a section called composites consisting of an accordion, carousel, flip, tabs and snippet component. Documentation notes that composite rendering consist of several renderings, each instance can have its own layout and it can be designed separately in Experience Editor. If you want to build your own composite components, you need to understand how they really work, which is actually more complex than they seem. Take the carousel for an example.

When you add a carousel to the page, you need to create a "Carousel" data source, which is actually a branch template defined in the Composites feature. In the branch template, two Carousel Slides are included by default, which have fields for "Slide Image", "Slide Text" and "Slide Link". 

When you add the carousel to the page, it has each slide viewable with all three fields. In experience editor you can select inside each slide and see that it's actually using a "Page Content" component to render these fields.

If you look at the cshtml source of the carousel, you'll find that the carousel is creating a placeholder for each slide.

<ul class="slides">
  @foreach (var composite in Model.CompositeItems)
  {
    var headerKey = string.Format("", baseKey, composite.Key, Model.Id);
    <li class="slide" @Html.Raw(composite.Key != 1 ? "style=\"display: none\"" : " ")>
    @using (Html.Sxa().BeginEditFrame(composite.Value.ID.ToString(), "Carousel", Model.IsControlEditable))
    {
       @Html.Sitecore().Placeholder(headerKey)
    }
    </li>
  }
</ul>

But when you look at the presentation details for the page, you'll note that there is but a single component on the page for the carousel. The contents of the placeholders show up in the page, but are not defined in the page's presentation details.

These are actually normally placeholders. You can actually navigate to each slide's placeholder and add other renderings or remove the default "Page Content" component. Any changes you make to these placeholders don't actually show up in the page's "Presentation Details" either.

So where and how are the "Page Content" components defined for each slide? They are actually defined on the Carousel Slide Item's themselves:

If you look into the details, you'll note that the Page Content component is actually setting the "Variant" to "Slide", which is actually defined globally in the Foundation Rendering Variants Feature:

So composites work by defining dynamic placeholders that will wire up components targeting the root of those placeholders on child items of the root data source. In the case of carousel, the root of the placeholder key is "section-content."

So if you wanted to create your own custom carousel, you could clone the component changing the Slide Items to have different fields, changing the slide item presentation details to use different renderings or different rendering variants.

But if you wanted to create your own component that leverages this approach, it is pretty straight forward. Your controller can inherit the "StandardController" like any SXA component, however you need to make sure your rendering model inherits "CompositeComponentRenderingModel" and your repository inherits "CompositeComponentRepository".

By doing so, when you call the "FillBaseProperties(model)" method in the repository, it will make sure the Composite Model is properly populated and when the view iterates "Model.CompositeItems" you'll loop through the child items of the data source properly.

Lastly, you also need to define "IsCompositeRendering" as one of the "Other Properties" of the rendering definition.

I recently followed these steps when creating the "Slick Carousel for Sitecore SXA" project, which is an alternative to the out of the box Carousel component that leverages the "Slick.js" library to provide better accessibility and more configurable options than the out of the box SXA carousel. You can review this project for examples of creating custom composite models and repositories and how everything wires together.

While the original "Slick" component just had an open placeholder for whatever components you wanted, the latest version takes the same approach as the SXA carousel and even leverages the same Slide data sources, allowing you to use the Slick and OOB carousels interchangeably on your site. You can find a ready to install Sitecore package on the releases tab on Github here.