How to design flexible layout with Dynamic Placeholder

In this article I will try to elaborate how to design flexible layout with Dynamic Placeholder.

There is lots of debate about how much flexibility we should give to the Content Author. Should we give the full flexibility to design a page from the scratch? Well the answer depends on the content author’s comfort level.

Sitecore 9 SXA it gives us the flexibility to design the page from the scratch (Although I didn’t explore it fully yet), but I’ll try to do it in old way using Dynamic Placeholder.

Before we go into the details the below nuget packages are required.

While implementing flexible design- the UX Designer, UI designer and Html Developer should be in the same page and they should have the common understanding about how the grid layout works.

Here I’ll try to implement one standard layout using Bootstrap Grid (One of the most popular css grid framework).

Here is my page layout.
PageLayout_p
The components are below:
1. Header
2. Carousel
3. CallAction
4. Our Business
5. What we do
6. Contact Us
7. Footer

My layout Page.cshtml looks like below:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap core CSS -->
    	<link href="//blackrockdigital.github.io/startbootstrap-half-slider/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    	<link href="//blackrockdigital.github.io/startbootstrap-half-slider/css/half-slider.css" rel="stylesheet">
    @Html.Sitecore().Placeholder("MetaInfo")
</head>
<body>
    @Html.Sitecore().Placeholder("Header")
<div class="container">
        @Html.Sitecore().Placeholder("Content")</div>
@Html.Sitecore().Placeholder("Footer")
    <!-- Bootstrap core JavaScript -->
    <script src="//blackrockdigital.github.io/startbootstrap-half-slider/vendor/jquery/jquery.min.js"></script>
    <script src="//blackrockdigital.github.io/startbootstrap-half-slider/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
</body>
</html>

There are 4 basic placeholders here
1. MetaInfo
2. Header
3. Content
4. Footer

The idea is that the components should be fixed for MetaInfo, Header and Footer placeholders but Content Author should be able to play with the “Content” placeholder.

To achieve flexible Layout we need to develop some basic structural components like below:
1. OneColumn
2. TwoColumn
3. ThreeColumn
etc.
For this demo I have developed two Structural Components “OneColumn” and “TwoCloumn”. As we may need to use these structural components more than once in a page so the placeholder names inside these structural components needs to be dynamic.
Here we need to use the Dynamic placeholders. I have used nuget packages available for the Dynamicplaceholders. But there is one problem that it appends current “RenderingId” to the placeholder names (PlaceHolderName_RenderingId) which is very difficult to play with. I read this nice article about the dynamic plaeholders and I wanted to use the same naming convention. So I tried write my own helper extension which is using the DynamicPlaceholder internally.

Below is the code for placeholder extension:

using DynamicPlaceholders;
using Sitecore.Mvc.Helpers;
using System;
using System.Web;

namespace BootstrapStructure.Helper
{
    public static class PlaceholderHelperExtension
    {
        public static HtmlString SiteDynamicPlaceholder(this SitecoreHelper helper, string placeholderName)
        {
            string placeholderName2 = PlaceholdersContext.Add(placeholderName, Guid.Empty, null);
            placeholderName2 = placeholderName2.Replace("_" + Guid.Empty.ToString(), "");
            return helper.Placeholder(placeholderName2);
        }
    }
}

It generates the placeholder names nicely like below:
“PlaceHolderName”, “PlaceHolderName_1”, “PlaceHolderName_2” and so on.

Now lets get into the details about structural components. Bootstrap uses two basic structural div “Row” and “column”. So my structural components should have these div as well. I have used rendering parameter templates for these structural components so that content author should have the flexibility.

OneColumn Component:

@if (RenderingHelper.GetRenderingParametersValueBool("RenderColumn"))
{
<div class="row @RenderingHelper.GetRenderingParametersValue("RowClass")">
<div class="col-lg-12 @RenderingHelper.GetRenderingParametersValue("ColumnClass")">
            @Html.Sitecore().SiteDynamicPlaceholder("Column_Content")</div>
</div>
}
else
{
<div class="row @RenderingHelper.GetRenderingParametersValue("RowClass")">
        @Html.Sitecore().SiteDynamicPlaceholder("Column_Content")</div>
}

If you see I gave the flexibility of append other class to “row” and “column” and also whether the “column” should be the part of structural component or not. Because some components can have “column” div as part of its own, in my case “Our Business” component has “column” div as part of itself.

The rendering parameters looks like below.
RenderingTemplate

TwoColumn Component:

<div class="row @RenderingHelper.GetRenderingParametersValue("RowClass")">
<div class="@RenderingHelper.GetRenderingParametersValue("LeftColumnClass")">
        @Html.Sitecore().SiteDynamicPlaceholder("Left_Column_Content")</div>
<div class="@RenderingHelper.GetRenderingParametersValue("RightColumnClass")">
        @Html.Sitecore().SiteDynamicPlaceholder("Right_Column_Content")</div>
</div>

I didn’t give default “column” class in the div as Content author can split the divs in any dimension (e.g 8 & 4, 9 & 3, 6 & 6 etc.)

The rendering parameters looks like below for “TwoColumn” component
RenderingTemplate-twoColumn

Once we done with the creating the page structure now we can insert other “Components” to the Structural Components placeholders.
My final page layout looks like below:

PresentationDetails

The full html output looks like below:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap core CSS -->
    	<link href="//blackrockdigital.github.io/startbootstrap-half-slider/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    	<link href="//blackrockdigital.github.io/startbootstrap-half-slider/css/half-slider.css" rel="stylesheet">
    <title>Flexible Design - Bootstrap Template</title>
    <meta name="description" content="">
    <meta name="keywords" content="">
</head>
<body>
    <!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
            <a class="navbar-brand" href="#">Start Bootstrap</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
	<li class="nav-item active">
                        <a class="nav-link" href="#">
                            Home
                            <span class="sr-only">(current)</span>
                        </a></li>
	<li class="nav-item">
                        <a class="nav-link" href="#">About</a></li>
	<li class="nav-item">
                        <a class="nav-link" href="#">Services</a></li>
	<li class="nav-item">
                        <a class="nav-link" href="#">Contact</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-lg-12 p-0">
<div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
	<li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
	<li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
	<li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
</ol>
<div class="carousel-inner" role="listbox">
<div class="carousel-item active" style="background-image: url('http://placehold.it/1900x1080')">
<div class="carousel-caption d-none d-md-block">
<h3>First Slide</h3>
This is a description for the first slide.</div>
</div>
<div class="carousel-item" style="background-image: url('http://placehold.it/1900x1080')">
<div class="carousel-caption d-none d-md-block">
<h3>Second Slide</h3>
This is a description for the second slide.</div>
</div>
<div class="carousel-item" style="background-image: url('http://placehold.it/1900x1080')">
<div class="carousel-caption d-none d-md-block">
<h3>Third Slide</h3>
This is a description for the third slide.</div>
</div>
</div>
<a class="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
                        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
                        <span class="sr-only">Previous</span>
                    </a>
                    <a class="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
                        <span class="carousel-control-next-icon" aria-hidden="true"></span>
                        <span class="sr-only">Next</span>
                    </a></div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="card text-white bg-secondary my-4 text-center">
<div class="card-body">

This call to action card is a great place to showcase some important information or display a clever tagline!</div>
</div>
</div>
</div>
<div class="row my-4">
<div class="col-lg-8">
                <img class="img-fluid rounded" src="http://placehold.it/900x400" alt=""></div>
<div class="col-lg-4">
<h1>Our Business</h1>
This is a template that is great for small businesses. It doesn't have too much fancy flare to it, but it makes a great use of the standard Bootstrap core components. Feel free to use this template for any project you want!

                <a class="btn btn-primary btn-lg" href="#">Call to Action!</a></div>
</div>
<div class="row">
<div class="col-sm-8">
<h2 class="mt-4">What We Do</h2>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. A deserunt neque tempore recusandae animi soluta quasi? Asperiores rem dolore eaque vel, porro, soluta unde debitis aliquam laboriosam. Repellat explicabo, maiores!

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Omnis optio neque consectetur consequatur magni in nisi, natus beatae quidem quam odit commodi ducimus totam eum, alias, adipisci nesciunt voluptate. Voluptatum.

                    <a class="btn btn-primary btn-lg" href="#">Call to Action »</a></div>
<div class="col-sm-4">
<h2 class="mt-4">Contact Us</h2>
<address>
                    <strong>Start Bootstrap</strong>

3481 Melrose Place

Beverly Hills, CA 90210

                </address>
<address>
                    <abbr title="Phone">P:</abbr>
                    (123) 456-7890

                    <abbr title="Email">E:</abbr>
                    <a href="mailto:#">name@example.com</a>
                </address></div>
</div>
</div>
<!-- Footer -->
<footer class="py-5 bg-dark">
<div class="container">

Copyright © Your Website 2017</div>
<!-- /.container -->
    </footer>

    <!-- Bootstrap core JavaScript -->
    <script src="//blackrockdigital.github.io/startbootstrap-half-slider/vendor/jquery/jquery.min.js"></script>
    <script src="//blackrockdigital.github.io/startbootstrap-half-slider/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Thanks All,

Humans are young species, they have much to learn – Optimus Prime

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s