How to create a Carousel in Umbraco using Nested Content and Bootstrap

Posted written by Paul Seal on December 19, 2017 Umbraco

What is Nested Content?

Nested content is a list editing property editor for Umbraco 7+. It is similar to Archetype, but not as full featured. It's more stripped back and simple which I think is the reason why it has been included in Umbraco Core since 7.7

Not only is it pleasant for the editor to use, it is also pleasant to code with, because you are essentially just coding against IPublishedContent items.

This post will show you how to do the following:

  • Use Nested Content to manage the content, images and links for a carousel
  • Write the necessary markup in Bootstrap for the carousel to work
  • Add an option to disable a slide, so you don't have to delete it if you want to turn it off temporarily.

Example of what we will create

Here is a demo site which uses a starter kit I created. That starter kit has a Carousel on the home page which is managed using Nested Content and is built using Bootstrap.

Lets start with Nested Content

Nested Content allows you to use normal Umbraco document types as items in a list.

Here is what the document type will look like

1

 

And here is what it will look like when it is used in the home page.

2

Composition

As nested content uses normal Umbraco document types, it also means that we can use document type composition.

This isn't a requirement but it is beneficial. Consider this example.

Our carousel slide will have the following properties:

  • Disabled (I'll talk more about this later)
  • Slide Title
  • Slide Subtitle
  • Slide Image
  • Slide Link

This is for our Main Carousel, but we may want a different carousel with similar properties, maybe it has no Subtitle, Image or Link.

With composition, we can create these in separate document types to allow us to compose the Nested Content document type.

3

Creating a Nested Content Data Type

Click on the Developer tab in the left menu.

Click on the 3 dots next to Data Types

Choose New data type.

    1. Enter the name Main Carousel
    2. In the Property editor dropdown, choose Nested Content
    3. In the Doc Types section, choose Carousel Slide
    4. Choose the Content tab
    5. And in the Template field, enter this:
      {{umbracoNaviHide == 1 ? '[Disabled] '  :  ''}}{{slideTitle}}
      The above bit of Angular will change the label for the item in the list. If it has Disabled ticked it will have [Disabled] in front of the name of the item.

    6. Enter the Min items allowed. I think if you leave it as zero then any are allowed.
    7. Enter the Max items allowed. I think if you leave it as zero then any are allowed.
    8. Confirm Deletes, if left ticked it will prompt the editor if they try to delete this item.
    9. Show Icons. You can leave this ticked to show the icon of the Carousel Slide document type in the list.
    10. You can tick this to hide the label of the Nested Content property which means you will have more space for editing the nested content items.
  1. Enter the name Main Carousel
  2. In the Property editor dropdown, choose Nested Content
  3. In the Doc Types section, choose Carousel Slide
  4. Choose the Content tab
  5. And in the Template field, enter this:
    {{umbracoNaviHide == 1 ? '[Disabled] '  :  ''}}{{slideTitle}}
    The above bit of Angular will change the label for the item in the list. If it has Disabled ticked it will have [Disabled] in front of the name of the item.

  6. Enter the Min items allowed. I think if you leave it as zero then any are allowed.
  7. Enter the Max items allowed. I think if you leave it as zero then any are allowed.
  8. Confirm Deletes, if left ticked it will prompt the editor if they try to delete this item.
  9. Show Icons. You can leave this ticked to show the icon of the Carousel Slide document type in the list.
  10. You can tick this to hide the label of the Nested Content property which means you will have more space for editing the nested content items.
{{umbracoNaviHide == 1 ? '[Disabled] '  :  ''}}{{slideTitle}}

Then click on Save

4

Now we have our Nested Content Document Type, we need to use it somewhere. We can either use Composition again, or we can add the property straight to the document type for the home page or whichever it will be used on.

  • Add a property called Main Carousel
  • Enter the description
  • Click on Add Editor
  • Click on Re-Use
  • Search for Main Carousel and Select it
  • Then click on Submit, Submit again and the click on Save

Add content

Now we have our property set up and working, we need to add some content.

Go to the page where you added the property, mine is the Home Page.

Click on the Plus symbol and start entering data for the fields.

5

Editing with Nested Content

Edit: You can edit the item by clicking on it to open it out first, then you can just start editing the values.

Re-order: You can re-order the items by dragging the crosshair icon on the item and moving it up or down.

Delete: You can delete the item by clicking on the delete icon.

Disable: Because we added the Disable tick box we can disable an item by ticking this box.

Rendering the carousel on the front end

Create a partial called "_MainCarousel.cshtml"

From the Template where you want to render the carousel, add this code:

Notice how easy it is to get the value of the Nested Content property and see that it returns an IEnumerable<IPublishedContent>

@inherits UmbracoViewPage

@using Umbraco.Web.Models

@{ 
    string carouselId = "mainCarousel";
    IEnumerable<IPublishedContent> carousel = Umbraco.AssignedContentItem.GetPropertyValue<IEnumerable<IPublishedContent>>(carouselId);
}

@if (carousel != null &amp;&amp; carousel.Any())
{
    <div class="carousel slide" data-ride="carousel" id="@carouselId">
        <div class="carousel-inner" role="listbox">
            @{
                int slideCount = 0;
                foreach (IPublishedContent slide in carousel.Where(x => x.IsVisible()))
                {
                    string title = slide.GetPropertyValue<string>("slideTitle");
                    string subtitle = slide.HasValue("slideSubtitle") ? slide.GetPropertyValue<string>("slideSubtitle") : "";
                    string imageUrl = slide.HasValue("slideImage") ? slide.GetPropertyValue<IPublishedContent>("slideImage").Url : "/img/carousel.jpg";
                    IEnumerable<RelatedLink> links = slide.GetPropertyValue<IEnumerable<RelatedLink>>("slideLink");
                    RelatedLink link = links != null ? links.FirstOrDefault() : null;

                    <div class="item @(slideCount == 0 ? "active" : "")">
                        <div class="jumbotron carousel-hero" style="background-image:url('@(imageUrl)');">
                            <h1 class="hero-title">@title</h1>
                            <p class="hero-subtitle">@subtitle</p>
                            <p><a class="btn btn-primary btn-lg hero-button" role="button" target="@(link.NewWindow ? "_blank" : null)" href="@link.Link">@link.Caption</a></p>
                        </div>
                    </div>
                    slideCount++;
                }
            }
        </div>
        <div>
            <a class="left carousel-control" href="#@carouselId" role="button" data-slide="prev"><i class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">Previous</span></a>
            <a class="right carousel-control" href="#@carouselId" role="button" data-slide="next"><i class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">Next</span></a>
        </div>
        <ol class="carousel-indicators">
            @for(int i = 0; i < slideCount; i++)
            {
                <li data-target="#@carouselId" data-slide-to="@i" class="@(i == 0 ? "active" : null)"></li>
            }
        </ol>
    </div>
}

Nested content items are treated as IPublishedContent so you can get values from them as you would any other document type. This makes it very easy to work with.

In the foreach loop, you will see I added a condition to say .Where(x => x.IsVisible())

This checks the Disabled property (umbracoNaviHide) and only shows the item if that value does not equal '1'.

If you remember the label value for the Nested Content item, we set it to be:

{{umbracoNaviHide == 1 ? '[Disabled] '  :  ''}}{{slideTitle}}

This uses the same logic.

Getting it to work with your Template

Here is an example template for you to see what is needed for this to work:

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css">
</head>
<body>
    @{ Html.RenderPartial("SiteLayout/_MainCarousel"); }
    @RenderBody()      
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>

It seems like a lot now that I've written it out, but the way you get the property values is a lot simpler than it was for Archetype, although Archetype had more functionality.

Further Help

If you're struggling to follow this and work best with an example already in place, then download my CodeShare Starter Kit and install it on a fresh install of Umbraco 7.7+. You can even install it from the back office in the packages library.

If you want to come back to this article later, I've created some short and memorable links for you, which all point to this page:

http://www.codeshare.co.uk/nestedcontent

http://www.codeshare.co.uk/nested-content

http://www.codeshare.co.uk/nc