Thursday, 6 April 2023

Sitecore Forms long labels truncated

The cause of this is fairly straightforward, but given how painful it is to debug I thought I'd post this for anyone else who comes across it.

If you are using Sitecore Forms, and ever have the need to use a very long label in a list item (eg. a checkbox list) you will notice it gets truncated. You may even note that the length is suspiciously similar to the max length of an item name...

After a lot of digging you'll note that these list item label/value strings are altered and set in Sitecore.ExperienceForms.Mvc.DataSource.DataSourceSettingsManager, specifically in the UpdateStaticItems method where there is a call to ItemUtil.ProposeValidItemName() for both label text and value. This is certainly required for one (if it's being set as the name or display name) however not for both.

Thanks to dependency injection the fix is nice and easy to patch in:

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"  xmlns:role="http://www.sitecore.net/xmlconfig/role/">
  <sitecore>
    <services>
      <register serviceType="Sitecore.ExperienceForms.FieldSettings.IFieldSettingsManager`1[[Sitecore.ExperienceForms.Mvc.Models.ListFieldItemCollection, Sitecore.ExperienceForms.Mvc]], Sitecore.ExperienceForms" 
        patch:instead="register[@serviceType='Sitecore.ExperienceForms.FieldSettings.IFieldSettingsManager`1[[Sitecore.ExperienceForms.Mvc.Models.ListFieldItemCollection, Sitecore.ExperienceForms.Mvc]], Sitecore.ExperienceForms']"
        implementationType="MyProject.Feature.Forms.DataSource.DataSourceSettingsManager, MyProject.Feature.Forms" lifetime="Transient" />
    </services>
  </sitecore>
</configuration>
/// <summary>
/// Overriding this class to fix issue where labels (eg. on checkbox list) are truncated
/// </summary>
public class DataSourceSettingsManager : Sitecore.ExperienceForms.Mvc.DataSource.DataSourceSettingsManager
{
protected override void UpdateSettings(ListFieldItemCollection settings, Item fieldSettingsItem, FieldSettingsContext settingsContext)
{
//base.UpdateSettings(settings, fieldSettingsItem, settingsContext);
Assert.ArgumentNotNull(settings, "settings");
Assert.ArgumentNotNull(fieldSettingsItem, "fieldSettingsItem");
Assert.ArgumentNotNull(settingsContext, "settingsContext");
if (settingsContext.FieldItem == null)
return;
if (MainUtil.GetBool(settingsContext.FieldItem.Fields["Is Dynamic"]?.Value, defaultValue: false))
{
foreach (Item child in fieldSettingsItem.Children)
child.Recycle();
return;
}
UpdateStaticItems(settings, fieldSettingsItem, settingsContext.FieldItem.Fields["Display Field Name"]?.Value, settingsContext.FieldItem.Fields["Value Field Name"]?.Value);
}
protected new void UpdateStaticItems(List<ListFieldItem> items, Item fieldSettingsItem, string displayFieldName, string valueFieldName)
{
Assert.ArgumentNotNull(items, "items");
Assert.ArgumentNotNull(fieldSettingsItem, "fieldSettingsItem");
for (int i = 0; i < items.Count; i++)
{
ListFieldItem listFieldItem = items[i];
if (string.IsNullOrEmpty(listFieldItem.Value))
{
listFieldItem.ItemId = "";
continue;
}
string text = ItemUtil.ProposeValidItemName(listFieldItem.Value);
Item item = (ID.IsID(listFieldItem.ItemId) ? fieldSettingsItem.Database.GetItem(listFieldItem.ItemId, fieldSettingsItem.Language) : null);
if (item == null)
item = AddItem(text, fieldSettingsItem, new TemplateID(Sitecore.ExperienceForms.Mvc.Constants.TemplateIds.ListFieldTemplateId));
else if (!item.Axes.IsDescendantOf(fieldSettingsItem))
item = item.CopyTo(fieldSettingsItem, text);
listFieldItem.ItemId = item?.ID.ToString() ?? string.Empty;
if (item != null)
{
if (string.IsNullOrEmpty(valueFieldName))
valueFieldName = (item.Template.IsBasedOnTemplate(Sitecore.ExperienceForms.Mvc.Constants.TemplateIds.ListFieldTemplateId) ? "Value" : "__ItemName");
item.Editing.BeginEdit();
item.Name = text;
item.Fields[valueFieldName]?.SetValue(listFieldItem.Value, force: false);
// Fix for labels being truncated
string value = !string.IsNullOrEmpty(listFieldItem.Text) ? listFieldItem.Text : listFieldItem.Value;
if (string.IsNullOrEmpty(displayFieldName) || item.Fields[displayFieldName] == null || displayFieldName == "__Display name")
value = ItemUtil.ProposeValidItemName(value);
((!string.IsNullOrEmpty(displayFieldName) && item.Fields[displayFieldName] != null)
? item.Fields[displayFieldName]
: item.Fields[FieldIDs.DisplayName]
)?.SetValue(value, force: false);
// End fix
item.Fields[FieldIDs.Sortorder]?.SetValue((i * 100).ToString(CultureInfo.InvariantCulture), force: false);
item.Editing.EndEdit();
}
}
foreach (Item child in fieldSettingsItem.Children)
{
if (!items.Exists((ListFieldItem li) => child.ID.ToString().Equals(li.ItemId, StringComparison.OrdinalIgnoreCase)))
{
child.Delete();
}
}
}
}

No comments:

Post a Comment