0

I am working on Sitecore 9.1 with SXA multisite application.

I have a folder in every site e.g Site-1/data/Tags/

I created page items with a field Multilist With Search type

Now I want to load data in this field only with Tags data belonging to that site only.

I am trying to pass source in 'multilist with search' like StartSearchLocation=query:$site/Data/Tag Repository/*[@@templatename='Tag']&Filter=+_templatename:Tag

But it does not work.

If I pass query like StartSearchLocation={11111111-1111-1111-1111-111111111111}&Filter=_template:{68BA23FD-8270-4675-97EA-4FAFC7CF3AB9}

then 'Multilist with Search' field loads data from all the sites.

Please suggest me how can I make sure data loads only from that site where item is created.

2

I don't think SXA provides this OOTB, we need to create QueryToken for Multlist With Search. The Multilist with Search field uses a SourceFilterBuilder class to parse its field source. Sitecore uses SourceFilterBuilderFactory to create the SourceFilterBuilder

You can follow this blog -

https://www.coreysmith.co/sxa-multilist-search-query-tokens/

Needs to extend SourceFilterBuilderFactory class -

using System;
using System.Linq;
using Sitecore;
using Sitecore.Buckets.FieldTypes;
using Sitecore.Data.Items;
using Sitecore.XA.Foundation.SitecoreExtensions.Services;

namespace CoreySmith.Foundation.SitecoreExtensions
{
  public class QueryTokenSourceFilterBuilderFactory : SourceFilterBuilderFactory
  {
    private readonly IQueryService _queryService;

    public QueryTokenSourceFilterBuilderFactory(IQueryService queryService)
    {
      _queryService = queryService ?? throw new ArgumentNullException(nameof(queryService));
    }

    public override SourceFilterBuilder CreateSourceFilterBuilder(Item targetItem, string fieldId, string fieldSource)
    {
      if (targetItem == null) throw new ArgumentNullException(nameof(targetItem));
      if (fieldId == null) throw new ArgumentNullException(nameof(fieldId));
      if (fieldSource == null) throw new ArgumentNullException(nameof(fieldSource));

      var startSearchLocation = StringUtil.ExtractParameter("StartSearchLocation", fieldSource);
      if (!StartSearchLocationContainsQueryToken(startSearchLocation))
      {
        return base.CreateSourceFilterBuilder(targetItem, fieldId, fieldSource);
      }

      var resolvedStartSearchLocation = ResolveStartSearchLocation(startSearchLocation, targetItem);
      var resolvedFieldSource = fieldSource.Replace(startSearchLocation, resolvedStartSearchLocation);
      return base.CreateSourceFilterBuilder(targetItem, fieldId, resolvedFieldSource);
    }

    private static bool StartSearchLocationContainsQueryToken(string startSearchLocation)
    {
      return !string.IsNullOrEmpty(startSearchLocation)
           && startSearchLocation.StartsWith("query:")
           && startSearchLocation.Contains("$");
    }

    private string ResolveStartSearchLocation(string startSearchLocation, Item targetItem)
    {
      var query = ParseStartSearchLocationIntoQuery(startSearchLocation);
      var resolvedStartSearchLocation = _queryService.Resolve(query, targetItem.ID.ToString());

      // Multilist with Search fields only support one StartSearchLocation. If a pipe-delimited list
      // is set on the field source, no results will be returned; instead, return the first result.
      var firstStartSearchLocation = resolvedStartSearchLocation.Split('|').FirstOrDefault();
      return $"query:{firstStartSearchLocation}";
    }

    /// <summary>
    /// The StartSearchLocation parameter requires '->' in place of '=' within Sitecore queries.
    /// For example: StartSearchLocation=query:/sitecore/content//*[@@template->'SomeTemplate']
    /// The SXA query token resolver doesn't like '->', so replace with '=' for the Sitecore
    /// query engine.
    /// </summary>
    private static string ParseStartSearchLocationIntoQuery(string startSearchLocation)
    {
      return startSearchLocation.Replace("->", "=");
    }
  }
}

Then register the QueryTokenSourceFilterBuilderFactory with Sitecore's DI container. This will replace the SourceFilterBuilderFactory implementation that Sitecore uses out of the box.

using Microsoft.Extensions.DependencyInjection;
using Sitecore.Buckets.FieldTypes;
using Sitecore.DependencyInjection;

    namespace CoreySmith.Foundation.SitecoreExtensions
    {
      public class SitecoreExtensionsConfigurator : IServicesConfigurator
      {
        public void Configure(IServiceCollection serviceCollection)
        {
          serviceCollection.AddSingleton<SourceFilterBuilderFactory, QueryTokenSourceFilterBuilderFactory>();
        }
      }
    }

Patch the configurator in through config:

<configuration>
  <sitecore>
    <services>
      <configurator type="CoreySmith.Foundation.SitecoreExtensions.SitecoreExtensionsConfigurator, CoreySmith.Foundation.SitecoreExtensions" />
    </services>
  </sitecore>
</configuration>

Then use it like below -

StartSearchLocation=query:$site/*[@@name='Data']/*[@@templatename='Video Folder']&TemplateFilter={ADE9EFF4-DA78-4E26-9248-B01BD93EAE95}
1
  • Thanks for your reply. I'll try. Sep 30 at 8:22

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.