3

I have a project with a defined folder structure for the renderings. I am in the process of adding SXA support and would like to create SXA Toolbox sections containing these renderings.

By default, Sitecore chooses the name of the section based on the parent folder a rendering is in, but I prefer not to use this as the defined folder structure gives meaningless names. I also would prefer not to change the defined folder structure.

There is a setting Group renderings in sections according to Available Renderings items in the site that changes this to use the Available Renderings name, however, this is applied for the whole site. As this would affect other sections I cannot make use of this setting.

Is there another way to configure the Toolbox section names, for example with a pipeline processor?

2
  • I don't understand why the option with the available renderings is not ok? Try sticking to ootb features, especially when it's nothing critical.
    – Gatogordo
    Jul 2 '19 at 14:57
  • As I am working on a library project, I would not like to enforce this upon the users of the library (as this is for the whole site)
    – MaartenKok
    Jul 2 '19 at 15:44
3

You could override and change the GetOrderedRenderings method in Sitecore.XA.Foundation.Editing.Service.AvailableRenderingsOrderingService to calculate the SectionName differently.

In the configuration the AvailableRenderingsOrderingService is registered as follows:

<register serviceType="Sitecore.XA.Foundation.Editing.Service.IAvailableRenderingsOrderingService, Sitecore.XA.Foundation.Editing" implementationType="Sitecore.XA.Foundation.Editing.Service.AvailableRenderingsOrderingService, Sitecore.XA.Foundation.Editing" lifetime="Singleton" patch:source="Sitecore.XA.Foundation.Editing.config"/>
1
  • Unfortunately the GetOrderedRenderings only is called when having the 'group by section name' checkbox checked. After looking into Sitecore.XA.Foundation.Editing.Dialogs.SelectRenderingForm this behaviour is confirmed...
    – MaartenKok
    Jul 3 '19 at 9:48
1

In the end I used a solution based on Joost's answer. It always returns true for GetOrdereredRenderings as that way Sitecore will always call the GetOrderedRenderings method. Then the checkbox is actually checked an the original logic is mimicked if it is not.

using System.Collections.Generic;
using System.Linq;
using MyProject.Foundation.Framework.Extensions;
using Sitecore.Data.Items;
using Sitecore.XA.Foundation.Editing.Models;
using Sitecore.XA.Foundation.Editing.Service;
using Sitecore.XA.Foundation.Multisite;
using Sitecore.XA.Foundation.Presentation;
using Sitecore.XA.Foundation.SitecoreExtensions.Repositories;

namespace MyProject.Foundation.Framework.Sxa
{
    /// <summary>
    /// Custom implementation of a IAvailableRenderingsOrderingService, which renames sections which contain MyProject renderings.
    /// </summary>
    public class MyProjectToolboxSectionRenamer : IAvailableRenderingsOrderingService
    {
        private readonly AvailableRenderingsOrderingService originalService;

        public MyProjectToolboxSectionRenamer(IPresentationContext presentationContext, IMultisiteContext multisiteContext, IContentRepository contentRepository)
        {
            originalService = new AvailableRenderingsOrderingService(presentationContext, multisiteContext, contentRepository);
        }

        public bool IsOrderingApplicable(Item siteItem)
        {
            //Always return true, as only then Sitecore calls GetOrderedRenderings.
            return true;
        }

        public IList<AvailableRenderingEntry> GetOrderedRenderings(Item siteItem, IList<Item> renderings = null)
        {
            if (renderings == null)
            {
                return null;
            }

            var orderedRenderings = GetDefaultOrderedRenderings(siteItem, renderings);
            ApplyMyProjectNames(orderedRenderings);
            return Reorder(orderedRenderings).ToList();
        }

        /// <summary>
        /// Retrieves the default ordered renderings (as Sitecore would retrieve it), do the actual check on whether or not ordering is applicable, as we skipped that in our implementation of IsOrderingApplicable.
        /// </summary>
        /// <param name="siteItem"></param>
        /// <param name="renderings"></param>
        /// <returns></returns>
        private IList<AvailableRenderingEntry> GetDefaultOrderedRenderings(Item siteItem, IList<Item> renderings)
        {
            return originalService.IsOrderingApplicable(siteItem)
                ? originalService.GetOrderedRenderings(siteItem, renderings) 
                : GetRenderingsBasedOnParentName(siteItem, renderings);
        }

        /// <summary>
        /// An implementation of building up the renderings with section names based on the parent nodes, based on Sitecore.XA.Foundation.Editing.Dialogs.SelectRenderingForm
        /// </summary>
        /// <param name="siteItem"></param>
        /// <param name="renderings"></param>
        /// <returns></returns>
        private IList<AvailableRenderingEntry> GetRenderingsBasedOnParentName(Item siteItem, IList<Item> renderings)
        {
            List<IGrouping<string, Item>> renderingsByParent = renderings.GroupBy(i => i.Parent.DisplayName).OrderBy(g => g.Key).ToList();
            var availableRenderings = new List<AvailableRenderingEntry>();
            foreach (var renderingByParent in renderingsByParent)
            {
                foreach (var rendering in renderingByParent.OrderBy(r => r.DisplayName))
                {
                    availableRenderings.Add(new AvailableRenderingEntry()
                    {
                        Order =  availableRenderings.Count,
                        RenderingItem = rendering,
                        SectionName = renderingByParent.Key
                    });
                }
            }
            return availableRenderings;
        }

        private void ApplyMyProjectNames(IList<AvailableRenderingEntry> orderedRenderings)
        {
            var myProjectRenderings = orderedRenderings.Where( ... Filter on only MyProject renderings ... );

            foreach (var rendering in myProjectRenderings)
            {
                rendering.SectionName = ... Determine custom name ...;
            }
        }

        private IEnumerable<AvailableRenderingEntry> Reorder(IEnumerable<AvailableRenderingEntry> orderedRenderings)
        {
            return orderedRenderings
                .OrderBy(x => x.SectionName)
                .ThenBy(x => x.RenderingItem.DisplayName);
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.