The Umbraco Grid is a great option to give Content Editors more control over the layout of pages and to allow for unstructured data to be effectively managed. However, the Grid is still fairly new and it can present implementation challenges for Umbraco designers and developers. One challenge is migrating content into the Grid. This could be migrating content from an existing site or, as in our case, from content on existing properties on each page.
The Challenge
This year one of our clients were planning a design refresh and loved how the Grid allowed more control of page layout. In addition, they were interested in making quick content additions without requiring a developer add new properties to Document Types. The challenge for us was: the client didn't want to re-enter all their content and manually create all the Grid layouts for each page.
Our first thought was to try to migrate the content from the properties into the grid. Content migration isn't very fun, but migrating content into the Grid is especially not fun (unless you're into that sort of thing). We have used CMS Import in the past with some success, but it didn't have any way to load content into the Grid easily.
This stumped us for a bit, until we got creative.
Our Solution: Hybrid Grid Editors
Rather than migrate the content into the Grid, we decided to leave the content in the existing page properties and reference them from the grid. Typically, Grid editors only reference data they control. In this case we needed to get a reference to the current page to access its properties. Luckily, it's possible with a little known property on the UmbracoHelper called AssignedContentItem.
Add this to the top of your Grid editor Partial View and you have yourself a nice strongly typed IPublishedContent.
@{
var currentPage = Umbraco.AssignedContentItem;
}
An Example of a Hybrid Grid Editor
I've put together a small example of a custom Grid editor that displays related blog posts. The blog posts are matched from a list of related tags on the page.
NOTE: If you're unfamiliar with creating custom Grid editors, review these articles to compare and contrast the methods:
Property
Here's the property that selects the tags on the Document Type:
Setup App_Plugins Folder
Now we setup our new Grid Editor in the App_Plugins folder of our Umbraco site. We will add a "CustomGridEditors" folder with a "RenderViews" folder to contain our front-end Partial Views and a "Views" folder for the backoffice rendering.
package.manifest
{
"gridEditors": [
{
"name": "Related Blog Posts",
"alias": "related-blog-posts",
"view": "/App_Plugins/CustomGridEditors/Editors/Views/related_blogs_view.html",
"render": "/App_Plugins/CustomGridEditors/Editors/RenderViews/RelatedBlogPosts.cshtml",
"icon": "icon-thumbnail-list"
}
]
}
related_blogs_view.html
<div style="padding-left:10px;">
<h3>Related Blog Posts</h3>
<p>This will list Blog Posts that match the tags selected on the Related Blog Tags property on the Related Blogs tab:</p>
<img src="/App_Plugins/CustomGridViews/Editors/Views/RelatedBlogsExample.png" style="width: 700px;" />
</div>
Add the Custom Grid Editor Into the Grid
After ensuring that the new Grid editor is available on my Grid Data Type and adding an appropriate example image (more on that below), I add the new Related Blog Posts editor to a Grid Layout on my test page.
Pro Tip: I prefer to create a Grid Layout named "Related Blog Posts" with the Related Blog Posts Grid editor as the only allowed editor. This allows Umbraco to automatically add the Related Blog Posts Grid editor without any extra clicks.
You may also notice that I'm using an example image to give a "real-time" preview of what the blog rendering might look like. However, I haven't found a way to reference properties on the same page from within an AngularJs controller that manages a custom Grid editor. It may be possible, but I haven't found it.
Now we can build the rendering view for the front-end.
Front-End View
RelatedBlogPosts.cshtml
@using Umbraco.Core.Models
@using Umbraco.Web
@inherits Umbraco.Web.Mvc.UmbracoViewPage<dynamic>
@{
var currentPage = Umbraco.AssignedContentItem;
var relatedTags = currentPage.GetPropertyValue<string[]>("relatedBlogTags");
// Extension Method to get content by tags
var relatedBlogPosts = Umbraco.GetContentByTags(relatedTags);
}
<div class="container">
<div class="row">
@foreach (var blogPost in relatedBlogPosts.Take(3))
{
var postImage = blogPost.GetCropUrl(310, 180, "postImage");
var excerpt = blogPost.GetPropertyValue<string>("excerpt");
<div class="col-sm-4">
<div class="card" >
<img class="card-img-top" src="@postImage" alt="Card image cap">
<div class="card-block">
<h4 class="card-title">@blogPost.Name</h4>
<p class="card-text">@excerpt</p>
<a href="#" class="btn btn-primary">Read this</a>
</div>
</div>
</div>
}
</div>
</div>
In this case I chose to query Examine for blogs that match. However, I didn't want to include all that query code in the partial view, so I created an Extension method on the UmbracoHelper to get the related blog posts from Examine.
That's all that is needed to create a Grid editor that pulls from properties outside the Grid. Really, you could copy existing Partial Views and use them almost exactly as they are with only the small modification to get the current page.
Copy/Paste Grid Layouts
One final item that was required to make the solution complete was copy/pasting an entire Grid with all its Layouts and Editors from one page to another. We did not create this piece. Instead we were lucky to hear a great talk from Anders at TeaSolutions about how they pimped out the Grid for some of their clients. In the talk they mentioned copy/paste functionality that they created and were kind enough to share it with us. I hear that they are planning on making it into a package...
It simply adds a couple of small links to the top of each Grid that allows Content Editors to copy/paste.
Benefits
We have been using the new structure for a month or two, but so far it hit the mark for keeping the migration pain low for the Content Editors. The real question is, is it worth using on other sites? Is it a good practice? Does it have legs? Here's what I see as the benefits.
It's familiar to long-time Umbraco Content Editors
If a client has been using Umbraco for ages and likes to know where to do everything, this method keeps them familiar and efficient.
Good for Content Editors who prefer filling out forms
The Grid is a bit more fiddly for infrequent or less technical Content Editors. This could be especially important on larger teams where a few Editors need a higher level of control and flexibility over layout, but many of the Editors want a simpler and more guided experience.
Easier to search using Examine
Searching the Grid content using examine can be a pain due to all the extra javascript data and structure that comes along with the content. There are some solutions, such as using the Skybrud.Umbraco.GridData package, but none of them are simple or right for every solution. This method allows for Examine to index the data properties the same as any other Umbraco properties on a page.
Eases the Content Migration burden for sites with existing data
For sites that have been around since v4 or v6 and have been upgraded to the current v7, this could give Content Editors the benefits of the Grid without a massive effort to move the Content into the Grid. By keeping the same properties and adding in the Copy/Paste functionality of the Grid, it's really quite fast so setup the Grid content quickly. It could also be used as an intermediate step to allow some time to slowly migrate the content into the Grid and normal Grid Data Editors.
Drawbacks
Here are some of the drawbacks I have found:
Cannot be used more than once in a Grid
If you add more than one Grid editor that references a property or set of properties on another tab, any newly added editors of the same type will render exactly the same as the original Editor on the page. This may seem obvious, but may not be to a Content Editor unfamiliar with the Grid and how it works.
There is potential for lots of tabs and properties to clutter DocTypes
If there are several Grid editors that reference data from Document Type properties, then the number of properties could become a usability issue. There are ways to mitigate this using Inline Help packages or other techniques. Just be aware of it and consider if the solution is creating new problems.
No "real-time" view of the Grid editor
We couldn't find a way to get the current page or access to properties on the current page. Unfortunately, this meant we couldn't show what the editor would look like in the backoffice with "real" data. We solved this by simply adding a static image of the editor from the front-end of the website.
Your Thoughts?
The jury is still out on this approach for us, but I'd love to hear feedback on the approach!
What are your thoughts? Any alternatives we could have considered? Any drawbacks that we didn't identify?