Conditional content properties in Optimizely
In a recent Optimizely project we were building multiple sites that could share content types between them. One problem we encountered was that some of the blocks and pages required slightly different content, and therefore separate content fields (known as properties). The simplest solution is to have 2 properties and if one is empty then the other one is used. The page or block can then display the content accordingly depending on what the content editor has provided.
The problem with that approach is that it becomes increasingly complex for the content editor and can result in content inconsistencies on the website. To solve this problem we developed a solution that could show or hide properties depending on the site that the shared content type is used. The use case in this article is for the properties to be conditional based on the site, however the same techniques can be applied to other similar use cases.
Transform metadata with custom attributes
Metadata is very important and useful in the Optimizely CMS because it controls how content is rendered in the editing view. The metadata of a property contains a bunch of setting values for things such as if the property is required, disabled or even hidden entirely. There are multiple ways to influence the metadata of a property — one option is to create a custom attribute that implements the IDisplayMetadataProvider
interface.
Hide a property based on the current site
What we're trying to achieve here is to show the property only when it is rendered for a specific site. The code sample below contains a custom attribute that accepts a parameter containing names of the sites that the property should be available for. The CreateDisplayMetadata
method from the IDisplayMetadataProvider
interface is then used to dynamically update the metadata to only display the property if the current site matches those sites.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
public class AvailableOnSitesAttribute : Attribute, IDisplayMetadataProvider
{
public IEnumerable<string> SiteNames{ get; }
public AvailableOnSitesAttribute(params string[] siteNames)
{
SiteNames = siteNames;
}
private bool IsCurrentSite()
{
return SiteNames.Any() && SiteNames.Contains(SiteDefinition.Current.Name, StringComparer.InvariantCultureIgnoreCase);
}
public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
{
if(context.DisplayMetadata.AdditionalValues[ExtendedMetadata.ExtendedMetadataDisplayKey] is ExtendedMetadata extendedMetadata)
{
extendedMetadata.ShowForEdit = IsCurrentSite();
}
}
}
There are many use cases where this type of attribute can be useful. It doesn't necessarily have to be based on the current site, it can be completely conditional based on any requirements. One thing to note is that it requires a page reload for the metadata to update, meaning that it's not an ideal method when the condition is related to another property on the same content type.
The custom attribute can be applied to any content type property. Below is a simple example of how a different introduction property can be displayed for the sites called Site1, Site2 and Site3. The names of the sites are configured in the 'manage sites' section of the admin UI.
[AvailableOnSites("Site1")]
public virtual string Intro { get; set; }
[AvailableOnSites("Site2", "Site3")]
public virtual XhtmlString DetailedIntro { get; set; }
Closing thoughts
The use case and examples in this article were somewhat simplified to make it less complex and confusing. To make things more robust you can adjust the metadata based on the site ID, or a site setting of sorts, instead of the name of the site.
As a final note I suggest customising the functionality to meet your requirements and firstly considering all your options — before you end up overcomplicating the properties on your content types. Handling properties this way can be very powerful and this article is meant to help developers meet specific requirements.
Subscribe to my newsletter
Read articles from Ynze Nunnink directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by