Grids are never really empty
The reason for this is that when you use property.Value("propertyAlias", fallback: Fallback.ToLanguage), the only scenario where fallback occurs, is when the value of that property is empty.When you make a new language version of an item and you do not put anything in the grid, it still is not empty, because what constitutes as an "empty" grid, actually looks like this.
{
"name": "1 column layout",
"sections": [
{
"grid": "12",
"rows": []
}
]
}
A second problem I encountered, is that the HtmlHelper-extension that is used to render your grid in a view only accepts a propertyAlias and under the hood it goes straight for the property in question, not through .Value(), preventing you from adding a similar workaround as in my previous article.
Fortunately Umbraco is Open Source, and the code for GetGridHtml is easily located.
public static MvcHtmlString GetGridHtml(this HtmlHelper html, IPublishedContent contentItem, string propertyAlias, string framework)
{
if (string.IsNullOrWhiteSpace(propertyAlias)) throw new ArgumentNullOrEmptyException(nameof(propertyAlias));
var view = "Grid/" + framework;
var prop = contentItem.GetProperty(propertyAlias);
if (prop == null) throw new NullReferenceException("No property type found with alias " + propertyAlias);
var model = prop.GetValue();
var asString = model as string;
if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty);
return html.Partial(view, model);
}
A new way of rendering
So, all I had to do was create my own class with my own extension method.Now what happens is:
- I get the value of the grid-property. With language fallback indicated, but that never happens, because a grid is never empty.
- If the grid is functionally "empty", I get the English value of the same grid-property.
- Normal processing resumes.
In my views, where - until now - I used the standard way of rendering grids, I had to add a using statement and change the name to my own extension method.
@using MyCode.Umbraco.Web.Extensions;
@inherits UmbracoViewPage<ContentPage>
@{
Layout = "BasePage.cshtml";
}
<div>
@Html.GetFallbackGridHtml(Model, ContentPage.GetModelPropertyType(c => c.Body).Alias, "site")
</div>
For those interested, here's the entire class. No rocket science, but it made my job just a little easier again.
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web;
using Umbraco.Web.Composing;
namespace MyCode.Umbraco.Web.Extensions
{
public static class GridExtensions
{
public static bool IsGridEmpty(object gridContent)
{
var asJToken = gridContent as JToken;
if (asJToken != null)
{
//Check all sections
var sections = asJToken["sections"] as JArray;
if (sections != null && sections.Any())
{
//If any section has any row --> not empty
foreach (var section in sections)
{
var rows = section["rows"] as JArray;
if (rows != null && rows.Any())
{
return false;
}
}
}
}
return true;
}
public static MvcHtmlString GetFallbackGridHtml(this HtmlHelper html, IPublishedContent content, string propertyAlias, string framework = "bootstrap3")
{
var gridContent = content.Value(propertyAlias, fallback: Fallback.ToLanguage);
//If gridcontent is "empty", do a fallback to defaultLanguage
if (IsGridEmpty(gridContent))
{
var defaultLanguage = Current.Services.LocalizationService.GetDefaultLanguageIsoCode();
gridContent = content.Value(propertyAlias, defaultLanguage);
}
return html.GetFallbackGridHtml(gridContent, framework);
}
public static MvcHtmlString GetFallbackGridHtml(this HtmlHelper html, object gridContent, string framework = "bootstrap3")
{
if (gridContent == null)
{
return new MvcHtmlString(string.Empty);
}
var view = "Grid/" + framework;
return html.Partial(view, gridContent);
}
}
}
No comments:
Post a Comment