Fix Broken Multilist With Search Field Sorting in SitecoreAI

> The non-negotiable setup that requires some Sitecore customization... but don't be scared
Cover Image for Fix Broken Multilist With Search Field Sorting in SitecoreAI

Background

As I established in a previous post, Sorting a Multilist with Search Field in SitecoreAI, the OOB authoring experience with Multililst with Search fields is quite bare bones in the sense that the default sorting is... Essentially random. You would think that the the default sort would be alphagettical based on item name/display name, but it is not. In this post, I show you how to set that up.

Overview

We accomplish alpha sort this by adding a computed field to the Solr index that returns a stable, case-insensitive alpha sort key for every item. The computed field returns the item's Display Name (falling back to the raw Item Name when Display Name is empty), lower-cased for case-insensitive ordering. The computed field is registered with returnType="string" so Solr stores it untokenized and sortable, which is what SortField=sortname[asc] in Multilist with Search sources relies on.

Aside from the code which you should mostly just be able to copy and paste, there are a few more gotchas to be aware of as well, so to my token-preserving robot greppers, please read the entire post before implementing this in your own solution.

Read the whole post before implementing

Code Setup

First, add a new CS file which defines the computed field.

SortNameField.cs
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.ComputedFields;
namespace XmCloudNextJsStarter.ContentSearch.ComputedFields
{
/// <summary>
/// Computed index field that produces a stable, case-insensitive alpha
/// sort key for every item.
///
/// Value precedence:
/// 1. The item's Display Name (the "__Display name" standard field) when set.
/// 2. Falls back to the raw Item Name when Display Name is empty.
///
/// Sitecore's <see cref="Sitecore.Data.Items.Item.DisplayName"/> already applies
/// that fallback, so this class only lower-cases the result to make Solr sorting
/// case-insensitive.
///
/// Registered with returnType="string" so Solr stores it untokenized and sortable,
/// which is what "SortField=sortname[asc]" in Multilist with Search sources relies on.
/// </summary>
public class SortNameField : IComputedIndexField
{
public string FieldName { get; set; }
public string ReturnType { get; set; }
public object ComputeFieldValue(IIndexable indexable)
{
var scIndexable = indexable as SitecoreIndexableItem;
var item = scIndexable?.Item;
if (item == null)
{
return null;
}
var displayName = item.DisplayName;
// ToLowerInvariant gives case-insensitive ordering only. It is NOT
// locale-aware collation, so diacritics are not folded (e.g. "e" and
// "é" do not sort together). Adequate for the alpha requirement.
return string.IsNullOrWhiteSpace(displayName)
? null
: displayName.ToLowerInvariant();
}
}
}

Then, add a patch config to register the computed field with the Solr index.

authoring/platform/App_Config/Include/zzz.Project.Indexing.config
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<indexConfigurations>
<defaultSolrIndexConfiguration>
<documentOptions>
<!--
Universal alpha sort key for Multilist with Search fields.
SortNameField returns the item's Display Name (falling back to the
raw Item Name when Display Name is empty), lower-cased for
case-insensitive ordering.
returnType="string" maps it to an untokenized Solr string field so it
is sortable via "SortField=sortname[asc]" in field source queries.
-->
<fields hint="raw:AddComputedIndexField">
<field fieldName="sortname" returnType="string">XmCloudNextJsStarter.ContentSearch.ComputedFields.SortNameField, XmCloudNextJsStarter</field>
</fields>
</documentOptions>
</defaultSolrIndexConfiguration>
</indexConfigurations>
</contentSearch>
</sitecore>
</configuration>

Lastly, and this may optional in your case, modify your deploy settings to ensure that the Solr schema is repopulated and the index is rebuilt after deployment.

xmcloud.build.json
{
"postActions": {
"actions": {
"populateSchema": {
"indexNames": [
"sitecore_master_index"
]
},
"reindex": {
"indexNames": [
"sitecore_master_index"
]
}
},
// If you have a lot of items, you may need to add/adjust the taskTimeOut
// See https://doc.sitecore.com/sai/en/developers/sitecoreai/deploying-sitecoreai/the-sitecoreai-build-configuration.html#change-the-post-action-timeout
"taskTimeOut": "01:00:00"
}
}

Pretty simple, but that's not all.

Field Source Setup

The code above is only as good as your field source setup. The most bulletproof field source structure looks like this:

StartSearchLocation=query:{xxxx-xxxx-xxxx-xxxx-xxxx}&TemplateFilter={xxxx-xxxx-xxxx-xxxx-xxxx}&SortField=sortname[asc]

This is no good:

StartSearchLocation=query:$site/Data/Services/*&TemplateFilter={xxxx-xxxx-xxxx-xxxx-xxxx}&SortField=sortname[asc]

Specifically, query:$site/Data/Services/* portion of StartSearchLocation. Apparently there are known issues regarding this syntax and wildcards, and therefore numerous landmines you might step on. I'm not saying all variations don't work -- I'm saying that you should test thoroughly to ensure the field renders/functions in Pages as you would expect (proper sorting, text search is ok, no items missing from the picker results when you scroll).

If The Changes Aren't Working

If after you deploy and are still not seeing the fields work correctly, you may need to:

  1. Refresh your Pages editor browser page
  2. Repopulate Solr managed schema for sitecore_master_index
  3. Manually rebuild sitecore_master_index -- if you have a lot of items, you may also need to increase the post-deployment reindex timeout in xmcloud.build.json to ensure that the reindexing job doesn't get interrupted
  4. Clear cache (yoursite.sitecorecloud.io/sitecore/admin/cache.aspx)
  5. Restart the instance
  6. If using IAR, verify that your template items aren't overridden in the database which would prevent your changes from being applied -- see my post on how to ensure that IAR database overrides won't kill your vibes

Wishlist

I wish that Multilist With Search fields were sorted alphagettically by default. I submitted a feature request which Sitecore officially logged feature request number CFW-9543.

In the meantime, you have your workaround, and possibly a mysterious craving for alphagetti.

Alphagetti joke

References

Stay sorted,

-MG

I chose these words

More Posts