Auto-output doctype template for Umbraco

This post is a continuation of this one. It discusses how to output a generic content page that loops through all properties of that page and outputs them automatically. So, for document types that are quite similar, only 1 template is required instead of 1 for each. Also, I’ve been looking at the zurb foundation reveal component, specifically using ajax to load content into it.

So, the other post talks about how to configure a landing page that contains a content lister that lists child pages, which can then be sorted and filtered etc. The next step is how to actually display the child page when its selected from the content lister. After toying with a few ideas, I decided that the solution would have to work in an accessible way (e.g. if no javascript), would have to allow deep linking to the actual page, but also present the content in a bit more of a fluid way. For this I decided to use zurb foundations reveal component.

Setting up the Umbraco template

To avoid the need to create loads of different templates for all the different document types, I created one that loops through all properties of the current document type and outputs the name and value. This was a little trickier than originally anticipated.  By just doing the following …

@foreach (var property in Model.Content.Properties){
 @property.PropertyTypeAlias : @property.Value
}

This outputs the alias of the property (not the display name) and only outputs the raw value. For text, this is great, but for media picker property types, it just outputs a number. So, I had to get the property type display name, and format the value based on that type.

Mapping the properties

To get all the properties of the current document type, I used this…

IEnumerable<PublishedPropertyType> propertyTypes = Model.Content.ContentType.PropertyTypes;

Then, when looping through the properties, the PropertyEditorAlias can be looked up (Umbraco.TrueFalse, Umbraco.MediaPicker etc) and used to format the value.

Mapper

To format each value correctly, I re-factored the property type mapper helper into its own helper class. The ‘MapPropertyType’ method accepts a property type alias and a value and maps the value according to its type. So, if its a media picker type, an image tag will be returned. If its a Date type, it will return a long date string.

@foreach (var property in Model.Content.Properties)
{
 if (property.HasValue)
 {
 <dt>@umbraco.library.GetPropertyTypeName(Model.Content.DocumentTypeAlias, property.PropertyTypeAlias)</dt>
 <dd>
 @Html.Raw(mapper.MapPropertyType(propertyTypes.SingleOrDefault((Func<PublishedPropertyType, bool>)(x =>
 {
 return x.PropertyTypeAlias.Equals(property.PropertyTypeAlias);
 })).PropertyEditorAlias, property.Value.ToString()))
 </dd>
 }
}

To actually get the display name of the property, the umbraco.library namespace has a ‘GetPropertyTypeName’ which accepts a document type alias and a property type alias. This returns the readable name of the property.

Outputting the content from the lister

To actually output the content page from the lister, I hooked into foundations reveal component. So, whenever a link is clicked from the lister, an ajax look-up is done and shown in a modal. It looks something like this…

directory-ajax-outputTo do this, I added a class to each link in the lister, which then allowed a little script to load and show the modal.

(function ($) {
 $('.directory-link').on('click', function () {
  var obj = $(this);
  $('#directory-modal').foundation('reveal', 'open', {
   url: obj.attr('href'),
   data: {
    fromAjax: true
   }
  });
  return false;
 });
})(jQuery);
 

So, whenever a link with a class of ‘directory-link’ is clicked, a modal is opened and populated with the content of an ajax request, with the links href used as the url. One other point to this is that parameters can be passed through with the ajax request, which can then be picked up via the querystring from the called page. Why is this needed?

Conditional formatting

If the page content was loaded via ajax, the template should not have an MVC ‘Layout’ specified, otherwise it would load all the page content as well as the form…

directory-item-all-formattingThis is not the desired behaviour if an ajax request is made. If the page is deep linked to, then yes, the entire site branding needs to be applied. So, by passing a parameter with the ajax request, this can be intercepted by the template page…

bool fromAjax = false;
bool.TryParse(Request.QueryString["fromAjax"] != null ? Request.QueryString["fromAjax"].ToString() : "false", out fromAjax);
Layout = fromAjax ? "" : "LCCLayout.cshtml";

This little snippet looks up a querystring value. If the request was an ajax one, there is no layout applied, so only the actual directory item html will be returned. If it wasn’t an ajax request, the entire site’s branding is applied. Simple, but effective.

Conclusion

This solution is accessible, allows deep linking to individual pages but also presents quite a nice dynamic way of showing content from the lister. Comments and suggestions always welcome.

 

Leave a Reply