Dusty Eves

dusty.eves@techno-babble.net

Sitecore Architect with Paragon Consulting

Sitecore Stenciling — Multi-Item Components

Introduction

This post assumes familiarity with the concept of stenciling.  If you’re not, I recommend a look at Intro to Sitecore Stenciling for some of the basic concepts.

Stenciling at the component levels give our content authors a starting point with our renderings that allows them to infer how the component is intended to be used.  This is useful for simple components but the gain is even more pronounced with complex components.  Take the example below:

Quote Component

One of two ways this component could be developed.  Either a collection of items belonging to a page or a component that pulls from a repository of quotes.  For our example we’re going to assume the former of the two options.  Given that our control will be composed of a set of child items, we’ll need to have an edit frame to make the insert options available in the Experience Editor.  (If you’re unfamiliar with how to implement insert options via edit frames, see my blog post here: Experience Editor Tips With Advanced IA)

Designing for the Experience Editor

Our first priority is to ensure all editing operations is accessible via the Experience Editor.  Marking the fields of the quotes as editable is simple enough. Assuming everything is editable, we start with our individual quotes rendering via the following view:

@using System.Collections.Specialized;
@inherits GlassView<Projects.Quotes.Models.IQuote>
<li>
    <blockquote>
        <div class="review-box">
            <div class="holder">
                <div class="frame">
                    <q>
                        @Editable(m => m.CopyText)
                        <img src="/theme/images/img3.gif" width="19" height="14" alt="image description" class="quotes-top" />
                        <img src="/theme/images/img2.gif" width="19" height="14" alt="image description" class="quotes-bottom" />
                    </q>
                </div>
            </div>
        </div>
        <cite>
            @using(BeginRenderLink(m => m.CTALink, new NameValueCollection { {"class","img-holder"}}, isEditable:true ))
            {
               @RenderImage(m => m.Image, isEditable: true)
            }
            
            <span class="user-details">
                <a href="@Model.CTALink.Url">@Editable(m => m.AuthorName)</a>
                <em>@Editable(m => m.Title)</em>
            </span>
        </cite>
    </blockquote>
</li>

This will render an individual quote with all the fields accessible, empowering the authors to control the quote content from the Experience Editor. This doesn’t yet give the content author the ability to add new quotes, remove or sort existing quotes.  We’ll tackle the problem of sorting and removing first.

Through the use of Edit Frames we can add access to item-level operations to the Experience Editor.  Our first step is to define the item operations we need.  In the core database we can define custom Edit Frame buttons under /sitecore/content/Applications/WebEdit/Edit Frame Buttons.  The edit frames are defined by an Edit Frame Button Folder and the WebEdit buttons that they contain.  The frame folder also allows you to define the Edit Frame’s title and default tooltips.  The buttons contained allow you to define the title, icon, tooltips of the buttons.  The most important property is the click field.  This defines the action taken.  The easiest way to create simple actions is to crib off of the buttons already present.  In the “Custom Experience Buttons” folder you’ll find all the operations we need for our edit frame Delete, Move Up, Move Down.  Copying the buttons from one folder to the other will get us what we need.

EditFrameButtons1

Once we’ve defined the buttons we just need to add the edit frame to our rendering like so:

@inherits GlassView<Projects.Quotes.Models.IQuote>
<li>
    @using (BeginEditFrame("/sitecore/content/Applications/WebEdit/Edit Frame Buttons/DeleteAndSort", Model.Path))
    { 
    <blockquote>
        <div class="review-box">
            <div class="holder">
                <div class="frame">
                    <q>
                        @Editable(m => m.CopyText)
                        <img src="/theme/images/img3.gif" width="19" height="14" alt="image description" class="quotes-top" />
                        <img src="/theme/images/img2.gif" width="19" height="14" alt="image description" class="quotes-bottom" />
                    </q>
                </div>
            </div>
        </div>
        <cite>
            @using(BeginRenderLink(m => m.CTALink, new NameValueCollection { {"class","img-holder"}}, isEditable:true ))
            {
               @RenderImage(m => m.Image, isEditable: true)
            }
            
            <span class="user-details">
                <a href="@Model.CTALink.Url">@Editable(m => m.AuthorName)</a>
                <em>@Editable(m => m.Title)</em>
            </span>
        </cite>
    </blockquote>
    }
</li>

One important aspect to note is the Model.Path.  Whatever operation the button executes will use the provided path as the relevant context.

Adding New Items

Enabling the addition of new quotes can be done with the same Edit Frame technique we used to allow deleting and sorting above.  Our starting point for the quotes rendering will likely look like this:

@using System.Collections.Specialized;
@using Quotes;

@inherits GlassView<QuoteSetViewModel>
<div class="block">
    <div class="holder">
        <div class="frame">
            <div class="content">
               @foreach (var quote in Model)
               {
                   @Html.Partial("/Views/Quotes.cshtml", quote, new ViewDataDictionary())
               } 
            </div>
        </div>
    </div>
</div>

As with the previous operations, we start by adding our Edit Frame definitions to the core database.  In this case, the operations we need are Insert and Sort:

Stencil2-EditFrameButtons2

Once defined we ad an edit frame to our view:

@using System.Collections.Specialized;
@using Quotes;

@inherits GlassView<QuoteSetViewModel>
@using (BeginEditFrame("/sitecore/content/Applications/WebEdit/Edit Frame Buttons/InsertAndSort", Model.Path))
{
<div class="block">
    <div class="holder">
        <div class="frame">
            <div class="content">
               @foreach (var quote in Model)
               {
                   @Html.Partial("/Views/Quotes.cshtml", quote, new ViewDataDictionary())
               } 
            </div>
        </div>
    </div>
</div>
}

One important thing to note, the insert operation will use the context of Model.Path. This requires setting the insert options on the quote container to the quote template to work effectively.

Like what you see? Something I missed? Have an even cooler way to do the same thing?!?! Let me know in the comments below.

Leave a Reply

Your email address will not be published. Required fields are marked *