Monthly Archives: April 2012

Building first Umbraco 5 website: Partials

The post you are reading now is the last one in a series of four blog posts describing my experience with creating a relatively simple Umbraco 5-based website for a made-up coffee shop.

  1. Building first Umbraco 5 website: Document Types
  2. Building first Umbraco 5 website: Nodes
  3. Building first Umbraco 5 website: Templates
  4. Building first Umbraco 5 website: Partials

The posts are written in a form of beginners’ tutorial and will take you through all the steps necessary for creating the website. Disclaimer: However, please keep in mind that I am in no way an expert or professional in the field. Therefore I submit to you a description of a learning process rather than an expert tutorial and I ask you to read it as such. More than that, I encourage you to commen,t to point out mistakes or suggest better practices.In the first three posts I:

  1. Explained the concept of document types
  2. Analyzed my website from the perspective of document types
  3. Created document types necessary for the website
  4. Explained the concept of nodes and explained how they are created
  5. Build the document structure for the website we are creating
  6. Showed you how to display content on your website using templates
  7. Explained the way to attach external stylesheets and JavaScript files to your website

In this post I will talk about partials and how to use them in your website. I will also show you the code used to complete the website we were working on. I will explain what the partials do in broad strokes but I will not go into much details. After you go through all the steps in this post, your website will be ready to post online.

Step 1: Partials in Theory

Partials are the life blood of Umbraco. They make sure that your page is dynamic and not everything has to be done manually. They are basically snippets of code written with Razor, which is an ASP.NET programming syntax used to create websites with the C#. For example you might remember that we didn’t want to hard-code the navigation in the header. We didn’t want it because that would mean that with every new page created by the administrator of our page, we would have to go into the code and add a new <li> to our <nav> list.  Partials are exactly the thing that will save us from doing that. We will add a piece of code to our website that will check for all child pages of the root and display them as navigation.

Creating New Partials

  1. In back office go to settings
  2. Right-click on Partials and choose create
  3. Give your partial a recognizable name
  4. Remember to save after editing
Creating New Partials in Umbraco 5

Using Partials in your templates

  1. Go to your template
  2. Place your cursor in the code where the partial should be executed
  3. Choose Insert Partial View from top menu
  4. Choose your partial from the list
  5. Click insert
Inserting Partials in Umbraco 5

Alternatively you can also type: @Html.Partial(“yourPartialsName”)in the templates code.

Step 2: Partials in Practice

To get our website to work we need 4 partials:

  1. For displaying images
  2. For top navigation
  3. For listing events on events page
  4. For displaying content on Menu page

The image partial (called: image) is this:

@inherits RenderViewPage
@using Umbraco.Cms.Web;</pre>
<img src="@Umbraco.GetMediaUrl(@Model.Field(" alt="" />
<pre>

This partial is really just one line of code and you could use it directly in your templates. You can go ahead and replace all @Umbraco.Field(“image”) in your templates with img src=”@Umbraco.GetMediaUrl(@Model.Field(“image”).ToString())”. Placing it in a separate partial introduces more order and organization to your code. Note that if you don’t have an image picked in your content section, this partial will actually cause an error. A more complicated partial that checks if the image hiveId exists is necessary to avoid this error.

This is top navigation (called: navigation):

@inherits RenderViewPage
@using Umbraco.Cms.Web
@using Umbraco.Cms.Web.Macros
@using Umbraco.Framework

@{
    @* Walks up the nodes tree from the current page to the rootNode *@
    var rootNode = DynamicModel.AncestorsOrSelf.Last();
}

@* Checks if the rootNode has children *@
@if (rootNode.Children.Any())
{</pre>
<ul>
	<li>@* Adds the rootNode to the navigation *@ <a href="@rootNode.Url">@rootNode.Name</a></li>
@* For each childPage of the rootNode add the child to the navigation as list item *@ @foreach(var childPage in rootNode.Children) {
	<li><a href="@childPage.Url">@childPage.Name</a></li>
}</ul>
<pre>}
  1. It starts by defining what rootNode is
  2. Then it checks if rootNode has children
  3. If there are children it starts by listing the rootNode (in our case the Home page)
  4. Then it lists the page name and makes it a link

Notice that we add HTML elements that should be created. For example the navigation items are enveloped in an unordered list and list item tags.

Listing events on events page (called: Sub Navigation):

@inherits RenderViewPage
@using Umbraco.Cms.Web
@using Umbraco.Cms.Web.Macros
@using Umbraco.Framework

@* Checks if the rootNode has children*@
@if(DynamicModel.Children.Any())
{</pre>
<div class="lable"><nav id="subnavi">
<ul>@* For each childPage of the rootNode *@ @foreach (var childPage in DynamicModel.Children) {
	<li><a href="@childPage.Url"> @childPage.Name
@childPage.Date
 </a></li>
}</ul>
</nav></div>
<pre>}

This partial basically does the same thing as the previous one, except it only lists the descendants of the page on which the partial is placed. In our case it will list all the particular event pages on the Events page.

Displaying content on Menu page (called: Inherit Content):

@inherits RenderViewPage
@using Umbraco.Cms.Web
@using Umbraco.Cms.Web.Macros
@using Umbraco.Framework

@* Check if rootNode has children*@
@if(DynamicModel.Children.Any())
{
    foreach (var childPage in DynamicModel.Children)
    {
    <ul class="menu">
        <li>
           <h1 class="section">@childPage.heading</h1>
           @if(childPage.Children.Any())
            {
                foreach (var grandchildPage in childPage.Children)
                {
                    <li>
                      <h3 class="item">@grandchildPage.menuItem</h3>
                      <span class="price">@grandchildPage.price</span>
                    </li>
                }
            }
        </li>
     </ul>
    }
}
  1. It checks if there are any children from the page on which this partial is used (these are menu sections)
  2. It lists the heading of the child page
  3. It checks if the childPage has any children (these are menu items)
  4. It lists the childPage child’s menuItem property value and price property value

Linking partials to templates:

  1. In your templates insert image partial everywhere you have @Umbraco.Field(“image”)
  2. Insert Inherit Content at the bottom of Menu template
  3. Insert Navigation into the Layout template between the <nav></nav> tags
  4. Insert the Sub Navigation partial into Events template just before the last </div> tag

The partials used in this website are all variations of the partials that you can find in the Umbraco 5 documentation on GitHub. You can learn much more by browsing this page.

Building first Umbraco 5 website: Templates

The post you are reading now is a third one in a series of four blog posts describing my experience with creating a relatively simple Umbraco 5-based website for a made-up coffee shop.
  1. Building first Umbraco 5 website: Document Types
  2. Building first Umbraco 5 website: Nodes
  3. Building first Umbraco 5 website: Partials

The posts are written in a form of beginners’ tutorial and will take you through all the steps necessary for creating the website.

Disclaimer: However, please keep in mind that I am in no way an expert or professional in the field. Therefore I submit to you a description of a learning process rather than an expert tutorial and I ask you to read it as such. More than that, I encourage you to commen,t to point out mistakes or suggest better practices.

So let’s get on with it. In the first two posts I

  1. Explained the concept of document types
  2. Analyzed my website from the perspective of document types
  3. Created document types necessary for the website
  4. Explained the concept of nodes and explained how they are created
  5. Build the document structure for the website we are creating

In this post I will explain how to make the content display on your website, using templates. I will begin by describing what templates are and how they look like. Then I will show you what to do to make your content display and how to style it.

Then I will move on to practical part of this post and show you how to create templates that will result (almost) in the website I showed you in the first post.

Step 1: Templates in Theory

Templates are files that store your html together with Razor syntax. The latter accounts for the dynamic aspects of your site, such as displaying content or generating navigation that updates automatically depending on what nodes you create. In this post I will only write about displaying content using Razor syntax but in the next one, you will learn about simple partials.

To create or edit templates:

  1. Go to back-office
  2. Choose Settings
  3. Click on Templates to see templates or right click on Templates to create a new one

creating templates with Umbraco 5

Templates folder always contains Layout which is your basic template. If you created any templates when creating document types (see: Document Types) then you will be able to see them here as well.

If you haven’t done anything with your layout template yet, this is how it’s going to look like.

<!DOCTYPE Html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    @RenderSection("head", false)
</head>
<body>
    @RenderBody()
</body>
</html>

This is your very basic Html5 document. It contains very little Html and no content. The reason for it is that you will add more Html and content in different templates that will then be rendered by Layout. If you have little experience with CMSs you might find it a bit confusing at first. But once explained, it will start making perfect sense. The two things you need to notice in the Layout file are:

@RenderSection(“head”, false)
@RenderBody()

These two belong with the Razor syntax and are basically responsible for rendering elements of templates that are child to Layout.

@RendeBody() will render everything that you put in the child template of Layout unless you mark it as a different section

@RenderSection(“head”, false) will render everything in the child template of Layout that you enter into section you define and call “head”. False means that the section is not required so a child template without this section will be rendered without errors (and true would of course mean the opposite).

Creating child templates with Umbraco 5

To create child template right click on layout and choose create. Then enter the name of your template (leave file extension as is) and press next.

Example of Child Template in Umbraco 5

You can now see that “New” my example child template is positioned underneath Layout in the template tree.
The first three line of code in the template editor are of no importance to us at the moment and they should stay as they are.
The next 3 lines of code define which template should be the parent of this one and provide the Html structure for it:

@{
Layout = “_Layout.cshtml”;
}

You can change this by changing the code or by choosing a different file from the dropdown menu in the top navigation of template editor. Once you change the parent template and save it, the template tree in the left window will change as well.
The next piece of code is how you define a section. Everything you enter between the curly brackets will be rendered in this section. Here we have head section that is rendered in the head of your html document but you can also define sidebar or footer section or any other section you see fit.

Everything you enter below the last curly bracket will be considered the body content and will be rendered by @RenderBody() in the Layout.

How to make content display on your website:

You should know by now how to assign templates to document types and nodes but if you can’t remember look back to posts 1 and 2 in this series.

For content to display on your website, you need to tell Umbraco which content should be displayed and where it should be displayed.
In the example Umbraco website above, I also created a node called Home of the document type Text Page, which has 2 properties called Heading (alias: heading, type: textstring) and Body Text (alias: bodyText, type:textarea). This document type is linked to template New.

Once you create the document type and node and fill it with some content you can move on to editing the template itself. (But don’t forget to publish your node).

  1. Go to Settings>Templates>New
  2. In the Template Editor window click on the “Insert an Umbraco Page Field” icon (second from the left)
  3. In the pop-up window open the Field dropdown

Insert Umbraco Property Button

Insert Umbraco Property Pop-up

You can see that you have several options to choose from bodyText and heading are the two properties you added. CurrentTemplateId, Name and UrlName are default fields and allow you to call metadata for the node (such as url or name).

  • Choose heading and click Insert
  • Make sure that the new line of code (@Umbraco.Field(“heading”)) is inserted below the last curly bracket (we want it to be rendered as body)
  • Repeat the process for bodyText

In the dropdown menu you will always be able to see ALL properties, created in ALL document types for your website. That means that you can insert a property that does not appear in the node that is linked to the template you are working on. This will not have any consequences. But that means that to limit the size of the dropdown it makes sense to call main body text in all document types “bodyText” and all headings “heading”( and all sidebar headings “sidebarHeading” etc.). This is also why it is so important to give descriptive names to properties rather than “prop1” “prop2” etc.

The line of code that actually inserts the content is very short and instead of inserting the property you can simply type the code (provided that you remember the alias you want to use).

  • Save template and navigate to your website (if you are not sure how to do that, go to your node, General Properties tab and click on the link)

On your website you should now be able to see the content you inserted in your Home node. Inspect the source code of the website to see where and how the content was inserted.

If you used textstring and textarea you will see that the content has no formatting whatsoever. It is just pure text .To give the text some format, go back to Template Editor and change the last two lines of code to:

<h1>@Umbraco.Field("heading")</h1>
<p>@Umbraco.Field("bodyText")</p>

Save the template and reload your Home page. Now content looks different and if you check the source code you will see that it also has proper markup.
Of course hardly any body text will consist of only one paragraph. This is solved by giving the bodyText property Rich Text Editor type. Every time you hit enter in the editor, new paragraph is created so when you call @Umbraco.Field(“bodyText”) the content will have the proper markup. You can edit the markup from within the RTE by clicking on the HTML button.

Adding Style

To add style to your content you proceed as per usual with your regular HTML/CSS websites. The only difference is that you can do it from within Umbraco.

  1. In back-office go to Stylesheets
  2. Click on the stylesheet you want to edit or right click on Stylesheets to create a new one

Umbraco 5 Stylesheet

RTE stylesheet refers to your Rich Text Editor and we will not be interested in that now. Site stylesheet is a default stylesheet and you can use if it you wish to, but it is not necessary.
For the purpose of this example we will create a new stylesheet called Layout and we will create the following styles:

h1, p
{
color:white;
background-color:black;
width:350px;
padding:10px;
}

Once you save this stylesheet move on to your Layout template and add this line of code:

<link rel="stylesheet" href="/content/styles/layout.css">

This line should go after the title tag. As you can see you link to your css files exactly the same way as you would otherwise. The only difference is the path which is a bit difficult to find the first time you work on your templates.

  • Images are also stored in the content folder: /content/images/yourimage.jpg
  • Jquery scripts are in: /scripts/jquery/yourscript.js

You can now navigate to your website and see the changes.

Step 2: Templates in Practice

Let’s move on to the New Coffee Café page we started building in previous posts.
Begin by creating the following templates:

Templates

Layout

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>

    <link rel="stylesheet" href="/content/styles/reset.css">
    <link rel="stylesheet" href="/content/styles/layout.css">

    @RenderSection("head", false)

</head>
<body>
    <header>
      <span>New Coffee Cafe</span>
      <nav>
      </nav>
    </header>
    <div id="content">
    	@RenderBody()
    </div>
    <footer>
      <div>
      <h3>Address: Green Street 25, NY</h3>
      <h4>Phone: 24 84 12</h4>
      </div>
    </footer>
</body>
</html>

Event

@inherits RenderViewPage
@using System.Web.Mvc.Html;
@using Umbraco.Cms.Web;
@{
	Layout = "_Layout.cshtml";
}

<div id="left">
  <h1>@Umbraco.Field("heading")</h1>
  <h2>@Umbraco.Field("date") @Umbraco.Field("cost")</h2>
      @Umbraco.Field("image")
      @Umbraco.Field("description")
</div>

<div id="right">
  <h1>@Umbraco.Field("headingRight")</h1>
      @Umbraco.Field("addressAndDetails")
</div>

Events

@inherits RenderViewPage
@using System.Web.Mvc.Html;
@using Umbraco.Cms.Web;
@{
	Layout = "_Layout.cshtml";
}

<div id="left">
  <h1>@Umbraco.Field("leftHeading")</h1>
      @Umbraco.Field("image")
      @Umbraco.Field("bodyText")
</div>

<div id="right">
  <h1>@Umbraco.Field("heading")</h1>

</div>

Menu

@inherits PartialViewMacroPage
@using Umbraco.Cms.Web
@using Umbraco.Cms.Web.Macros

@inherits RenderViewPage
@using System.Web.Mvc.Html;
@using Umbraco.Cms.Web;
@{
	Layout = "_Layout.cshtml";
}

@section head
{
	<link rel="stylesheet" href="/content/styles/menu.css">
}

Text Page


@inherits RenderViewPage
@using System.Web.Mvc.Html;
@using Umbraco.Cms.Web;

@{
	Layout = "_Layout.cshtml";
}

<div id="left">
  <h1>@Umbraco.Field("leftHeading")</h1>
      @Umbraco.Field("image")
      @Umbraco.Field("bodyText")
</div>

<div id="right">
  <h1>@Umbraco.Field("heading")</h1>
  <div class="lable">
    <ul>
       <li>@Umbraco.Field("row1Lable")</li>
       <li>@Umbraco.Field("row2Lable")</li>
       <li>@Umbraco.Field("row3Lable")</li>
       <li>@Umbraco.Field("row4Lable")</li>
       <li>@Umbraco.Field("row5Lable")</li>
       <li>@Umbraco.Field("row6Lable")</li>
    </ul>
  </div>
  <div class="value">
    <ul>
       <li>@Umbraco.Field("row1Value")</li>
       <li>@Umbraco.Field("row2Value")</li>
       <li>@Umbraco.Field("row3Value")</li>
       <li>@Umbraco.Field("row4Value")</li>
       <li>@Umbraco.Field("row5Value")</li>
       <li>@Umbraco.Field("row6Value")</li>
     </ul>
  </div>

</div>

Then move on to Stylesheets and create the following stylesheet with the following code.

Layout

body{
  width:1000px;
  background:white;
  margin:auto;
  font-family:"Arial Rounded MT Bold";
}

#content{
  width:1000px;
  background:#D6D3C2;
  float:left;
}

header{
  background:#666666;
  height:200px;
  color:#FFD34F;
  padding-top:30px;

}

header span{
  font-size:50px;
  margin-left:30px;
  margin-top:30px;
}

footer{
  background:#666666;
  clear:both;
}
footer div{
  width:1000px;
  margin:auto;
}

footer h3, h4{
  font-family:"Arial Rounded MT Bold";
  color:#FFD34F;
  text-align:center;
}

nav ul{
  margin-top:104px;
  float:right;
}

nav ul li{
  float:left;
  border: 1px solid #D6D3C2;
  padding:10px;
}

nav ul li a{
   color:#FFD34F;
   text-decoration:none;
   font-size:25px;
}

nav ul li a:hover{
   color:#FFD34F;
   text-decoration:underline;
   font-size:25px;
}

nav#subnavi ul{
   margin-top:-5px;
   width:200px;
   float:none;
}

nav#subnavi ul li{
   padding:0px;
}

nav#subnavi ul li a{
   margin-top:-10px;
   color:black;
   font-size: 15px;
   line-height:20px;

}

nav#subnavi ul li a:hover{
   text-decoration:underline;
}

h1{
  font-size:25px;
  color:#666;
  padding:40px 40px 40px 0;
}

h2{
  margin-top:-37px;
  margin-bottom:20px;
  font-size:15px;
  font-family:"Myriad Pro";
}

div#left {
  width:550px;
  margin-left:40px;
  margin-bottom:40px;
  float:left;
}

div#left img{
   margin-right:15px;
   float:left;
}

div#left p{
   font-size:15px;
   font-family:"Myriad Pro";
   line-height:18px;
}

div#right{
   margin-left:690px;
}

div#right p{
   margin-bottom:10px;
   line-height:18px;
}

.lable{
   float:left;
   margin-right:30px;
   line-height:20px;
}

.lable ul li a p{
  font-size:13px;
  font-family:"Myriad Pro";
}

.value{
   font-family:"Myriad Pro";
   font-size:15px;
   line-height:20px;
}

Menu

ul.menu{
   float:left;
   margin:15px 30px 30px 15px;
}

h1.section{
   padding:2px;
   width:200px;
   background:#FFD34F;
   font-size:18px;
   margin-bottom:9px;
}

h3.item{
  float:left;
  width:190px;
}

Reset

/* http://meyerweb.com/eric/tools/css/reset/
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
	display: block;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}
table {
	border-collapse: collapse;
	border-spacing: 0;
}
  1. If you now navigate to the website you will see that it looks almost as it should. The few things that are missing and/or look wrong are listed below. And I will fix them using partials. You can read about it in the next post.
  2. Instead of images you will see a long string of letters and numbers. This string is the id of the media item. This is the strangest little quirk of Umbraco. In order to display media content you need to use Razor syntax to convert the media id into an actual image. It seems strange and I don’t know why this solution has been implemented.
  3. There is no navigation. We could of course hard code navigation into our templates but that means that when user creates new nodes the navigation will be outdated. Instead we will make Umbraco dynamically generate the navigation.
  4. On the Events page no event list is visible. And again we could hard code the list but the dynamic solution makes so much more sense.
  5. The Menu page is empty. The reason for that is that we never told the Menu template to render the content from Menu Sections and Menu Items.
We will look at all these problems in the next post and solve them with Partials – the life force of Umbraco.