10

How do I define DataSource Location for rendering parameters, relative to the context item?

When defining a DataSource Location for rendering parameters (Droplink or TreeList etc), using a relative XPath query (./ or ancestor-or-self etc), it seems that the DataSource Location is relative to the actual rendering item and not the context item.

2 Answers 2

15

DataSource Location inside rendering parameters has different context.

You could achieve your goal by extending resolveRenderingDatasource pipeline.

Allows developers to override the default logic for resolving the data source for renderings.

Pipeline args type is: ResolveRenderingDatasourceArgs and it contains:

public string Datasource { get; set; }

You can find you context item like that:

Item item = args.CustomData["contextItem"] as Item ?? Context.Item;

Having raw value of Datasource field (value from Standard Values of your rendering parameters) with your query and context item, you could execute your query to get results in correct context.

By reading Datasource property you can access that value from Standard Values before it is resolved by Sitecore.

Then you can process it and convert to an item ID running query not in Rendering item context (like Sitecore would normally do without your intervention, situation that you described) but in Context Item context.

Datasource property in your case contains (relative XPath query (./ or ancestor-or-self etc))

0
2

The accepted answer is correct in most scenarios. However, I have come across a unique one that it does not satisfy.

Disclaimer: Avoid anything other than ID's for the datasource to save yourself a lot of headaches.

Workflow/Modular Content

Workflow bundling was added in version 8.2. This allows content authors to move dependent page content through a shared workflow without having to move each rendering/datasource individually. For example, if your page changes from Draft to Staged, any dependent datasource items will automatically be moved to Staged as well. This is all courtesy of the new setting:

<setting name="WebEdit.AffectWorkflowForDatasourceItems" value="true" patch:source="Sitecore.ExperienceEditor.config"/>

After sorting through some Sitecore plumbing the following command is ultimately executed:

<command name="webedit:workflowwithdatasourceitems" type="Sitecore.ExperienceEditor.WebEdit.Commands.WorkflowWithDatasourceItems, Sitecore.ExperienceEditor" />

This command does execute Item.Visualization.GetRenderings(). This method runs the resolveRenderingDatasource pipeline and should return your datasources properly. The problem is that the Sitecore.Context.Item is null when executed from the webedit:workflowwithdatasourceitems which means when it ultimately runs the resolveRenderingDatasource pipeline- all of your queries will fail since you don't have a Context Item to reference.

Thankfully, the fix is quite simple. Patch the webedit:workflowwithdatasourceitems command and wrap with a ContextItemSwitcher:

using System;
using Sitecore;
using Sitecore.Data.Items;
using Sitecore.ExperienceEditor.Utils;
using Sitecore.Workflows.Simple;

namespace Common.CustomSitecore.Commands
{
    [Serializable]
    public class WorkflowWithDatasourceItems : Sitecore.Shell.Framework.Commands.Workflow
    {
        [UsedImplicitly]
        protected new void WorkflowCompleteCallback(WorkflowPipelineArgs args)
        {
            base.WorkflowCompleteCallback(args);

            using (new ContextItemSwitcher(args.DataItem))
            {
                var definedDatasources = ItemUtility.GetItemsFromLayoutDefinedDatasources(args.DataItem, Context.Device, args.DataItem.Language);
                definedDatasources.AddRange(ItemUtility.GetPersonalizationRulesItems(args.DataItem, Context.Device, args.DataItem.Language));
                definedDatasources.AddRange(ItemUtility.GetTestItems(args.DataItem, Context.Device, args.DataItem.Language));

                foreach (var filterSameItem in ItemUtility.FilterSameItems(definedDatasources))
                {
                    if (filterSameItem.Access.CanWrite() && (!filterSameItem.Locking.IsLocked() || filterSameItem.Locking.HasLock()))
                        WorkflowUtility.ExecuteWorkflowCommandIfAvailable(filterSameItem, args.CommandItem, args.CommentFields);
                }
            }
        }
    }
}

Patch

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <commands>
      <command name="webedit:workflowwithdatasourceitems" type="Sitecore.ExperienceEditor.WebEdit.Commands.WorkflowWithDatasourceItems, Sitecore.ExperienceEditor">
        <patch:attribute name="type">Common.CustomSitecore.Commands.WorkflowWithDatasourceItems, Common</patch:attribute>
      </command>
    </commands>
  </sitecore>
</configuration>

AGAIN: Avoid anything other than ID's for the datasource to save yourself a lot of headaches.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.