Sitecore Experience Accelerator – What is new in rendering data source

I recently started looking into the features of Sitecore Experience Accelerator module and in this post I will share my understanding for few new ways of assigning datasource to a rendering that comes with SXA.

Motivation

With the new concept of page/partial design in SXA I noticed following things those motivated me to know more about it and write this blog post.

1. Relative Data Source:
The first thing I noticed is the datasource field value as relative path in the rendering. As you can see in the below image, the selected item is a partial design item named as “Footer” and the control properties window shows the relative datasource for a control with some special starting keyword as “local” and after that a relative item path.

SXA-datasource-1

Figure 1: Page Relative Datasource

Clearly it means there must be some resolvers those will be doing the magic of converting a relative path to full item path.
The questions are which resolver is doing that? And are there any more resolvers?

2. Datasource change is not allowed from page for a rendering that belongs to partial design:
On a page if rendering is coming from partial design than from that page content authors cannot change the datasource for the item. The datasource can only be set on the partial design itself.

But lets assume there is a requirement to design a product detail page with using partial design. A rendering should be there in the partial design that must pick the content from product item field itself.
The question is does SXA has any solution?

Findings

Let’s start from Sitecore configuration, showconfig.aspx contains following resolvers to resolve rendering datasources:

SXA-datasource-2

Figure 2: SXA pipeline processors to resolve datasource for renderings

There are six resolvers but in this post I am I will cover the three processors highlighted in the box.

1. Field Datasource
A field name from Context Item can be given in datasource and SXA will do following:

  • If the field type is link field than the target item id will be used as datasource.
  • If the field type is not link field and field value is not empty than field raw value will be used as datasource.

This method of datasourcing can solve the problem discussed for product detail page design in the motivation section.

Pipeline Processor:
<processor type="Sitecore.XA.Foundation.LocalDatasources.Pipelines.ResolveRenderingDatasource.DatasourceFromField, Sitecore.XA.Foundation.LocalDatasources" patch:source="Sitecore.XA.Foundation.LocalDatasources.config"/>

Syntax:
field:{FIELD NAME}

Example:
field:Title

2. Code Datasource:
A custom class can be created and type name of the class can be passed in the datasource. The custom class must implement the interface Sitecore.Buckets.FieldTypes.IDataSource. This interface contains single method named ListQuery. The method signature is as follows:

Item[] ListQuery(Sitecore.Data.Items.Item item)

As per the method signature, a Sitecore item will be retrieved as input and array of item will be returned. The resulting data source will be the IDs list of all items returned.

Pipeline Processor:
<processor type="Sitecore.XA.Foundation.LocalDatasources.Pipelines.ResolveRenderingDatasource.CodeDatasource, Sitecore.XA.Foundation.LocalDatasources" patch:source="Sitecore.XA.Foundation.LocalDatasources.config"/>

Syntax:
code:{FULLY QUALIFIED TYPE NAME}

Example:
code:SXA.POC.DataSources.CodeDataSource,SXA.POC


3. Page Relative Datasource
Instead of giving the full path of the item, a relative path can be passed that will be evaluated in respect of the Context Item, SXA will get the full path of the context item, appends the relative path mentioned in datasource at end and creates a full item path. This new full item path will be used as datasource value for the rendering. This resolver is used for the Relative Data Source item I mentioned in motivation section.

Pipeline Processor:
<processor type="Sitecore.XA.Foundation.LocalDatasources.Pipelines.ResolveRenderingDatasource.PageRelativeDatasource, Sitecore.XA.Foundation.LocalDatasources" patch:source="Sitecore.XA.Foundation.LocalDatasources.config"/>

Syntax:
page:{RELATIVE PATH}
local:{RELATIVE PATH}

Example:
page:/contact-us

Sample Code

Let’s create a sample to verify the above discussion.

To keep it simple I am creating a simple view rendering that will only render the datasource value and nothing else. Here is the rendering code:

<p>Datasource value is = @RenderingContext.Current.Rendering.DataSource</p>

1. Page Relative Datasource
I have few items created under the home page and one of those is “About Us” page. I have placed the rendering on home page and used the relative page path in data source.

SXA-datasource-3

Figure 3: Page Relative Datasource assignment in presentation

Once published we can see the full item path on the page:

SXA-datasource-4

Figure 4: Page Relative Datasource result

2. Field Datasource
I have placed the rendering on the home page and used the field data source method and used the field name as “title”.

SXA-datasource-5

Figure 5: Field Datasource assignment in presentation

Once published we can see the title field value on the page:

SXA-datasource-6

Figure 6: Field Datasource result

There is no sample in this post with a link field but that is easy to do. You can add a link field to the page template and assign it a target Sitecore item. After that just go to the presentation details and change the field name to your link field name, publish all changes and open the page, you will see the item id of the item selected in link field.

3. Code Datasource
Let’s first decide what should the custom code must perform. For simplicity I want to build a custom code functionality that will treat all children item from the context item as datasource. Let’s add a custom data source class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Sitecore.Buckets.FieldTypes;
using Sitecore.Data;
using Sitecore.Data.Items;
namespace SXA.POC.Datasources
{
  public class CodeDataSource : IDataSource
  {
    public Item[] ListQuery(Sitecore.Data.Items.Item item)
    {
      var l = newList<Item>();
      if (item.Children != null)
      {
        foreach(var child in item.Children)
        {
          l.Add(child asItem);
        }
      }
     return l.ToArray();
    }
  }
}

Build the solution and publish.

At the Sitecore end we have two items under the home item, let’s check their IDs first.

SXA-datasource-7

Figure 7: First child item under home

SXA-datasource-8

Figure 8: Another child item under home

Now let’s place the code source in the rendering data source:

SXA-datasource-9

Figure 9: Code Datasource assignment in presentation

Once published we can see the IDs of children pages on the home page:

SXA-datasource-10

Figure 10: Code Datasource result

Conclusion

Sitecore provides several ways to assign data source to a rendering. The existing data souring ways include providing full path of the Sitecore item, providing a Sitecore item ID or writing a query. SXA adds some new ways for data souring and gives more flexibility and power to the Sitecore architectures to design the solution.

GlassView with strongly typed context item and model

I have recently started working with Sitecore MVC using glass mapper. In my project I have several view renderings where I need to access the details of datasource item and as well as current context item. I knew that GlassView class takes the type of model as generic type argument and then if there is data source mentioned for the view rendering then it creates the model from data source item otherwise it creates the model from current context item.

Here my requirement was to use both (model as my data source and current context item) as strongly typed objects in my view renderings. Hence I started to look into the GlassView class and found some interesting public methods and properties that are useful to developers:

Properties:

S.No. Name Purpose
 1. ContextItem Returns the item specified by the current context item.
 2. DataSourceItem Returns the item specificed by the data source only. Returns null if no datasource set.
 3. LayoutItem Returns either the item specified by the DataSource or the current context item.

 

Methods:

S.No. Name Purpose
 1. GetContextItem Returns the Context Item as strongly typed.
 2. GetDataSourceItem Returns the Data Source Item as strongly typed.
 3. GetLayoutItem Returns the Layout Item as strongly typed.
 4. GetRenderingParameters Returns the parameters as strongly typed.

 

As there is out of box support available for strongly types in GlassView for data source and as well as context item so we started with defining a variable in our view renderings as below:

@inherits GlassView<MyDataSource>@{

var pageItem = GetContextItem<MyContentItem>();

}

<div>@pageIem.Title</div>

 

But this was tedious to verify that developers in my team were using this strongly typed approach instead of using the context item directly so I created small abstract class by inheriting from GlassView:

public abstract class CustomGlassView<TModel, TPageItem> : GlassView<TModel>where TModel : classwhere TPageItem : class

{

private TPageItem pageItem;

public TPageItem PageItem

{

get { return pageItem ?? (pageItem = this.GetContextItem<TPageItem>()); }

}

}

 

Now in my view renderings I am able to put the two strongly types for my view class as below:

@inherits CustomGlassView<MyDataSource, MyContentItem><div>@PageItem.Title</div>

This helps a lot in working with view renderings and the same can be done for parameters.

Thanks.