allBlogsList

SXA Multi Sort

I recently had the need to implement a multi-sort using an SXA Sort Results component. The only advice I could find after searching was to implement it from the front-end since the URL hash allows multiple, but in our case, we need the sort dropdown to drive the multi sort, not the URL hash.

After decompiling and following the Search Results logic for sorting, I ended up in SortingService and OrderingParametersParserService. Looks like if I just add some extra logic for parsing the facet parameter in OrderingParametersParserService, the SortingService will just add the sort (and reverse it…). Basically, I can expand on this logic found in Sitecore.XA.Foundation.Search.Services.OrderingParametersParserService:

ObjectIndexerKey objectIndexerKey = (ObjectIndexerKey) (obj[Sitecore.Buckets.Util.Constants.FacetParameters] ?? string.Empty);
orderingFacetList.Add(new OrderingFacet()
{
Direction = defaultDirection,
Facet = obj,
Key = objectIndexerKey
});

Since the Facets Field Name help text says, “You can enter multiple field names in a comma-separated list,” which doesn’t actually work for sort, I decided to make it work. I replaced OrderingParametersParserService with my own implementation.

<configuration xmlns:patch\="http://www.sitecore.net/xmlconfig/"\>  
        <sitecore\>  
              <services\>  
                    <register serviceType\="Sitecore.XA.Foundation.Search.Services.IOrderingParametersParserService, Sitecore.XA.Foundation.Search"                                        implementationType\="Sitecore.XA.Foundation.Search.Services.OrderingParametersParserService, Sitecore.XA.Foundation.Search"  
lifetime\="Singleton" >  
<patch:attribute name\="implementationType"\>Feature.Search.Services.OrderingParametersParserService, Feature.Search</patch:attribute\>  
                    </register\>  
              </services\>  
        </sitecore\>  
</configuration\>

For the code, simply loop on the facet parameter value Split by comma result, and add the orderingFacetList like the original:

var facetParameters = facetItem.Fields[Sitecore.Buckets.Util.Constants.FacetParameters].Value;

foreach (var facetParameter in facetParameters.Split(',')) {

orderingFacetList.Add(new OrderingFacet
{
Direction = defaultDirection,
Facet = facetItem,
Key = facetParameter
});
}

When adding the fields to the facet in Sitecore, don’t forget they need to be in reverse order from how you want them to sort.

SXA Multi Sort Image 1

What if one/multiple of your additional sorts needs to be in a different direction than the one defined on your Sorting item? The OrderingFacet has a direction on it, so we just need to add the check for it. Let’s add the ability to have an optional bar separator to add direction. Something like this, where the Sorting is descending but field2 needs to be ascending.

SXA Multi Sort Image 2

With a few adjustments to the foreach to account for the new direction, the final code looks like this:

foreach (var facetParameter in facetParameters.Split(','))
{
ObjectIndexerKey objectIndexerKey = facetParameter.Split('|')[0];
var direction = defaultDirection;
// Bar indicates this facet contains a direction different from the sort item.
if (facetParameter.Contains("|"))
{
var facetDirection = facetParameter.Split('|')[1];
Enum.TryParse(facetDirection, true, out direction);
}
orderingFacetList.Add(new OrderingFacet
{
Direction = direction,
Facet = facetItem,
Key = objectIndexerKey
});
}