Sitecore Page Editor Tips and tricks – component datasource versions part 2

In my previous post I built a rule that would hide a component based on some criterias regarding the datasource item. In the Page Editor these hidden component would show as grey blocks which is nice since you get a clear indication that there’s a component and that it isn’t translated. But now what? A natural next step would be to be able to add a version of that component to be able to translate it.

My main idea was to add a button to the component in the page editor, visible when the component was greyed out. When clicked would add a version in the current language of the related item.

As I didn’t realy know if things would work or not, my approach was kind of touch and go. My first goal was to add a button when the component was hidden (greyed out). On a rendering you can add additional buttons visible for that component when in the Page Editor using the Page Editor Buttons. However once a rendering is hidden it will be switched in the Page Editor to another rendering and all the configured Page Editor Buttons would disappear. You could probably add buttons to the Hidden Rendering which will replace the original rendering, but I didn’t have that in mind at the time 🙂

I went with adding a Default Rendering Button, which is located here in the Core database /sitecore/content/Applications/WebEdit/Default Rendering Buttons/. This is where all default buttons for a component is located such as the Edit Related item, Change Position and so on. So I created a button.

 

Then I created a class inheriting the WebEditCommand. I didn’t know what to expect when the button executed the command. If I would get the datasouce item out of the box or if I would have to manually find it in some way. But it turned out to be quit easy. If the rendering had no datasource configured the CommandContext object passed to the command would give the current item and if the datasource was set it would pass that item instead. Since this was a default rendering button, it would be visible for all renderings all the time. So I had to override the QueryState and write my own to hide the button if the item had a version. Below is the resulting command:

public class AddDatasourceVersion : WebEditCommand
    {
        public override void Execute(CommandContext context)
        {
            Assert.ArgumentNotNull((object)context, "context");
            Item obj = context.Items[0];
            if (obj.Versions.Count > 0) return;
            using (new SecurityDisabler())
            {
                obj.Versions.AddVersion();
            }
        }
        public override CommandState QueryState(CommandContext context)
        {
            Assert.ArgumentNotNull((object)context, "context");
            Item obj = context.Items[0];
            return obj.Versions.Count > 0 ? CommandState.Hidden : CommandState.Enabled;

        }
    }

A command was defined and configured for the button, I went with:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore>
    <commands>      
      <command name="custom:adddatasourceversion" type="Lab.Sample.Commands.WebEdit.AddDatasourceVersion,Lab.Sample"/>
    </commands>
  </sitecore>
</configuration>

A recommendation though! For best user experience, use Standard Values with prefilled dummy data, because it can be hard to find the component once a version has been added if there is no content or any obvious graphical elements 😉

Sitecore Page Editor Tips and tricks – component datasource versions

Out of the box, Sitecore does nothing if a components datasouce doesn’t exist or if there aren’t any versions in the current language. This means that you will have to handle this your self.
Well I thought that it would be nice to let the rules engine in Sitecore handle this.

My plan was to create a global conditional rendering rule that would check the following criterias:

  • Is the Rendering Item of the current rendering configured with a Datasource Template?
  • If not, ignore the following statements and display the rendering!
  • Does the rendering have any datasource set?
  • Does the datasource exist?
  • If the datasource item is a media item, the next statement should be ignored and the rendering displayed.
  • Does it have any versions in the current language?

If it would fail on any of these statement, the rendering should be hidden. Since there weren’t any existing condition which did this, I had to build it my self. Things said and done and the result was this:

public class HasItemVersionForDatasource : OperatorCondition
      where T : ConditionalRenderingsRuleContext
    {
        protected override bool Execute(T ruleContext)
        {
            var renderingItem = ruleContext.Item.Database.GetItem(ruleContext.Reference.RenderingID);
            var dsLocation = renderingItem.Fields["Datasource Location"].Value;
            var dsTemplate = renderingItem.Fields["Datasource Template"].Value;
            if ((dsLocation.Length > 0 || dsTemplate.Length > 0) && string.IsNullOrEmpty(ruleContext.Reference.Settings.DataSource)) return false;
            else if (string.IsNullOrEmpty(ruleContext.Reference.Settings.DataSource)) return true;

            var datasourceitem = ruleContext.Item.Database.GetItem(ruleContext.Reference.Settings.DataSource);
            return datasourceitem.Paths.IsMediaItem || datasourceitem.Versions.Count > 0;
        }
    }

This condition was added to Sitecore and enabled for the Conditional Rendering Rules. Since the condition doesn’t take any parameters you can write anything you like, I went with “where the renderings datasource has item version”.
A new rule at /sitecore/system/Settings/Rules/Conditional Renderings/Global Rules was created using the new condition looking like this:

 

With this now set up, all renderings with a datasource which doesn’t have any version in the current language will be hidden. And in the Page Editor they will be visible as grey blocks like this:

 

That’s it, pretty usefull right? 😀 Now you’ll be relieved from performing null-checks and so on in each component. And also you will get a clear indication in the Page Editor that there are components that aren’t translated.

Note that this only handles guid and path based datasources and not query based datasources. However it could surely be extended.

I will follow up with some additional post regarding Page Editor tips and tricks 😀