I'm going to try and make this not a link only answer.
What you are trying will not work because the renderings fields (shared and final) want to store the ID
of the data source item. If you just type in a path to an item that does not exist, it will not be able to work out an ID
.
If you want to make sure that Datasources are set when the item is created, a better way would be to use a Branch Template. This way you can have your datasource items created at the same time as you create your page item.
Use a Branch Template
So create your structure in the branch template area, and create all your datasource items, pointing the rendering datasources at the branch template/page/. You would get something like this:
Branch Templates
- $name
- Page Item
- Data Source Content 1
- Data Source Content 2
- etc...
Good so far...
Fix Up Sitecore
Now we need to fix Sitecore - because when Sitecore creates the items from the branch templates, it will keep the original ID's of the items from the branch template location.
Fortunately there is already a fix for that. @Kamsar wrote up a nice fix here for Branch Datasource Presets. This modifies the addFromTemplate
pipeline from the itemProvider
group. I will include the code here so this doesn't become a link only answer. All credit for code goes to @Kamsar.
Configuration changes:
<!-- Add this to App_Config/Include to enable branch presets -->
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<group name="itemProvider" groupName="itemProvider">
<pipelines>
<addFromTemplate>
<processor type="BranchPresets.AddFromBranchPreset, BranchPresets" />
</addFromTemplate>
</pipelines>
</group>
</pipelines>
</sitecore>
</configuration>
And this is the code that gets run to fix the datasource locations:
public class AddFromBranch : Sitecore.Pipelines.ItemProvider.AddFromTemplate.AddFromTemplateProcessor
{
public override void Process(AddFromTemplateArgs args)
{
Assert.ArgumentNotNull(args, nameof(args));
if (args.Destination.Database.Name != "master") return;
var templateItem = args.Destination.Database.GetItem(args.TemplateId);
Assert.IsNotNull(templateItem, "Template did not exist!");
// if this isn't a branch template, we can use the stock behavior
if (templateItem.TemplateID != TemplateIDs.BranchTemplate) return;
Assert.HasAccess((args.Destination.Access.CanCreate() ? 1 : 0) != 0, "AddFromTemplate - Add access required (destination: {0}, template: {1})", args.Destination.ID, args.TemplateId);
// Create the branch template instance
Item newItem = args.Destination.Database.Engines.DataEngine.AddFromTemplate(args.ItemName, args.TemplateId, args.Destination, args.NewId);
// find all rendering data sources on the branch root item that point to an item under the branch template,
// and repoint them to the equivalent subitem under the branch instance
RewriteBranchRenderingDataSources(newItem, templateItem);
// now go through all descendants to translate their data sources
var newItemDescendants = newItem.Axes.GetDescendants();
for (int i = 0; i < newItemDescendants.Length; i++)
{
RewriteBranchRenderingDataSources(newItemDescendants[i], templateItem);
}
args.Result = newItem;
}
protected virtual void RewriteBranchRenderingDataSources(Item item, BranchItem branchTemplateItem)
{
string branchBasePath = branchTemplateItem.InnerItem.Paths.FullPath;
LayoutHelper.ApplyActionToAllRenderings(item, rendering =>
{
if (string.IsNullOrWhiteSpace(rendering.Datasource))
return RenderingActionResult.None;
// note: queries and multiple item datasources are not supported
var renderingTargetItem = item.Database.GetItem(rendering.Datasource);
if (renderingTargetItem == null)
Log.Warn("Error while expanding branch template rendering datasources: data source {0} was not resolvable.".FormatWith(rendering.Datasource), this);
// if there was no valid target item OR the target item is not a child of the branch template we skip out
if (renderingTargetItem == null || !renderingTargetItem.Paths.FullPath.StartsWith(branchBasePath, StringComparison.OrdinalIgnoreCase))
return RenderingActionResult.None;
var relativeRenderingPath = renderingTargetItem.Paths.FullPath.Substring(branchBasePath.Length).TrimStart('/');
relativeRenderingPath = relativeRenderingPath.Substring(relativeRenderingPath.IndexOf('/')); // we need to skip the "/$name" at the root of the branch children
var newTargetPath = item.Paths.FullPath.Replace("Home", "").Replace("Global", "").TrimEnd('/') + relativeRenderingPath;
var newTargetItem = item.Database.GetItem(newTargetPath);
// if the target item was a valid under branch item, but the same relative path does not exist under the branch instance
// we set the datasource to something invalid to avoid any potential unintentional edits of a shared data source item
if (newTargetItem == null)
{
rendering.Datasource = "INVALID_BRANCH_SUBITEM_ID";
return RenderingActionResult.None;
}
rendering.Datasource = newTargetItem.ID.ToString();
return RenderingActionResult.None;
});
}
There is a bit more to the code, so please get it from @Kamsar's blog post and github repo.
This should get you where you want to be with presetting the datasource items relative to the page item.
__Standard Values
item to use to point the datasource at?./Data source item name