Skip to main content

Custom Fields in Sitecore (Custom DropLink, DropTree, MultiList, TreeList and Required Field Validator)

Custom Fields in Sitecore Just thought to share few of the custom Sitecore fields that I have created for one of the sample project. This may help the community memebers to easily incorporate them into their project if they need any of them. Here are few.
1. Custom DropLink
  
using Sitecore.Data.Items;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    public class CustomDropLink : Sitecore.Shell.Applications.ContentEditor.LookupEx
    {
        protected override void DoRender(System.Web.UI.HtmlTextWriter output)
        {
            this.ExcludeItems();
            base.DoRender(output);
        }

        private void ExcludeItems()
        {
            Item item = Sitecore.Context.ContentDatabase.GetItem(base.ItemID);
            var LinkedField= Sitecore.StringUtil.ExtractParameter("ParentField", this.Source);
            var fieldvalue = item.Fields[LinkedField].Value;
            NameValueCollection parameter = HttpUtility.ParseQueryString(Source);
            parameter["datasource"] = fieldvalue;
            this.Source = HttpUtility.UrlDecode(parameter.ToString());           
        }
    }
}
  
  

2. Custom DropLink
  
using System;
using System.Collections.Generic;
using System.Web.UI;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Shell.Applications.ContentEditor;
using System.Linq;
using System.Configuration;
using SitecoreCustom.Extensions.Constants;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    public class CustomDropTree : Tree
    {
        private bool hasValidSource;
        public CustomDropTree()
        {
            Class = base.Class + " ftFieldTreeExtended";
            base.Activation = true;
        }
        public new string Source { get; set; }
        public static bool HasSourceChanged = false;
        /// 
        /// Validate the valid source item, if not been selected, prompt user with a message.
        /// 
        /// HtmlTextWriter
        protected override void DoRender(HtmlTextWriter output)
        {
            if (hasValidSource)
            {
                this.Attributes["onchange"] = "HideDependentFields(this, true)";
                base.DoRender(output);
                return;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.ServerProperties["Value"] = this.ServerProperties["Value"];
        }
        /// 
        /// OnLoad event.  Override the OnLoad event to inject our DataSourceField 
        /// when the selected value of the data source field changes.
        /// 
        /// 
        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                base.Source = this.Source;
                var fieldValue = ConfigurationManager.AppSettings["ContentItemGUID"];
                if (IsPathOrGuid(fieldValue) && !SourceContainsDataSource())
                {
                    var sourceItem = ResolveItem(fieldValue);
                    if (sourceItem != null)
                    {
                        base.Source = String.Format("{0}&DataSource={1}", Source, sourceItem.Paths.Path);
                        this.Value = SanitizeValues(sourceItem, Value);
                    }
                    hasValidSource = true;
                    SetModified();
                }
            }
            if (Sitecore.Context.ClientPage.IsEvent)
            {
                string str = Sitecore.Context.ClientPage.ClientRequest.Form[this.ID + "_value"];
                if (str != null)
                {
                    if (base.GetViewStateString("Value", string.Empty) != str)
                    {
                        //TreeList.SetModified();
                    }
                    base.SetViewStateString("Value", str);
                }
            }

            base.OnLoad(e);
        }
        /// 
        /// If they are not children of the item in DataSourceField, remove GUIDs from a list of selected values 
        /// 
        /// Selected Item in field specified by DataSourceField
        /// Current value of the TreeList field
        /// List of values that are descendents of TreeList fields source.
        private string SanitizeValues(Item sourceItem, string value)
        {
            var db = GetDatabase();
            if (value == null || String.IsNullOrEmpty(value.Trim())) return String.Empty;
            var ids = value.Split('|');
            var validItems = new List();
            for (int i = 0; i < ids.Length; i++)
            {
                var item = db.GetItem(new ID(ids[i]));
                if (item.Axes.IsDescendantOf(sourceItem))
                    validItems.Add(item);
            }
            return String.Join("|", validItems.ConvertAll((x) => x.ID.ToString()));
        }
		
        private bool SourceContainsDataSource()
        {
            return this.Source.ToLower().Trim().StartsWith("datasource=") || this.Source.ToLower().Contains("&datasource=");
        }
       
        private string GetDataSourceField()
        {
            return StringUtil.ExtractParameter("DataSourceField", Source).Trim().ToLower();
        }
        /// 
        /// Gets 'DataSource' value from Source query parameters
        /// 
        public new string DataSource { get { return StringUtil.ExtractParameter("DataSource", Source).Trim().ToLower(); } }

        /// 
        /// Returns the value of a field from Data Source.
        /// 
        /// fieldName is the field being used as a Data Source
        /// Value of the Data Source.
        private string GetSourceFromField(string fieldName)
        {
            if (String.IsNullOrEmpty(fieldName)) return String.Empty;
            Item item = CurrentItem();
            if (item == null) return String.Empty;
            Field field = item.Fields[fieldName];
            if (field == null) return String.Empty;
            string fieldValue = field.GetValue(true);
            if (fieldValue == null) return String.Empty;
            return fieldValue;
        }

        private Item CurrentItem()
        {
            return Sitecore.Context.ContentDatabase.GetItem(new ID(base.ItemID));
        }
		
        private bool IsPathOrGuid(string fieldValue)
        {
            return Sitecore.Data.ID.IsID(fieldValue) || fieldValue.StartsWith("/", StringComparison.OrdinalIgnoreCase);
        }
        /// 
        /// Takes string of guid or a path and returns Item set in DataSourceField  
        /// 
        /// string of guid path or Item found in the field specified by DataSourceField
        /// Item
        private Item ResolveItem(string fieldSource)
        {
            var db = GetDatabase();
            Assert.ArgumentNotNull(db, "Database");

            if (db == null) return null;

            if (Sitecore.Data.ID.IsID(fieldSource))
                return db.GetItem(new ID(fieldSource));

            if (fieldSource.StartsWith("/", StringComparison.OrdinalIgnoreCase))
                return db.GetItem(fieldSource);

            return null;
        }
		
        private new Database GetDatabase()
        {
            return Sitecore.Context.ContentDatabase;
        }

        private string GetTypeDatasource()
        {
            Item item = CurrentItem().Parent;
            if (item != null)
            {
                string customControlParentFieldName = ConfigurationManager.AppSettings["CustomControlParentFieldName"];
                if (item.Fields[customControlParentFieldName] != null && !string.IsNullOrWhiteSpace(item.Fields[customControlParentFieldName].Value))
                {
                    string type = item.Fields[customControlParentFieldName].Value;
                    Item typeItem = ResolveItem(type);
                    if (typeItem != null)
                    {
                        string typeName = typeItem.Name;
                        string dataSource = StringUtil.ExtractParameter(CMSConstants.CustomDataSource, Source).Trim();
                        if (!string.IsNullOrWhiteSpace(dataSource))
                        {
                            List typeDataSources = new List();
                            typeDataSources = dataSource.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            if (typeDataSources != null && typeDataSources.Count() > 0)
                            {
                                foreach (string typeSource in typeDataSources)
                                {
                                    if (typeSource.ToLower().Contains(typeName.ToLower()))
                                    {
                                        string sourceGuid = typeSource.ToLower().Replace(typeName.ToLower() + ":", string.Empty);
                                        return sourceGuid;
                                    }
                                }
                            }
                        }                   
                    }
                }
            }
            return string.Empty;
        }
    }
}
 
 

3. Custom MultiList
  
using System;
using System.Collections.Generic;
using System.Web.UI;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Shell.Applications.ContentEditor;
using System.Linq;
using System.Configuration;
using SitecoreCustom.Web.Extensions.Constants;
using System.Web;
using System.Text;
using Sitecore.Globalization;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    public class CustomMultiList : MultilistEx
    {
        private bool hasValidSource;
        public CustomMultiList()
        {
            // css class
            Class = base.Class + " ftFieldTreeListExtended";
            base.Activation = true;
        }
        // source values
        public string Source { get; set; }
        public static bool HasSourceChanged = false;
        /// 
        /// Validate the valid source item, if not been selected, prompt user with a message.
        /// 
        /// HtmlTextWriter
        protected override void DoRender(HtmlTextWriter output)
        {
            if (hasValidSource)
            {
                base.DoRender(output);
                return;
            }
        }
        /// 
        /// OnLoad event.  Override the OnLoad event to inject our DataSourceField 
        /// when the selected value of the data source field changes.
        /// 
        /// 
        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            Item parentItem = null;
            string fundComponentName = string.Empty;

            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                var fieldValue = ConfigurationManager.AppSettings[CMSConstants.ComponentItemGUID];
                var db = GetDatabase();
                var includeTemplates = HttpUtility.HtmlDecode(GetTypeIncludeTemplates());
                Sitecore.Data.Items.Item[] labelItems = null;
                Sitecore.Data.Fields.MultilistField components = null;
                parentItem = CurrentItem().Parent;
                if (labelItems != null)
                {
                    foreach (Item labelItem in labelItems)
                    {
                        components = (Sitecore.Data.Fields.MultilistField)labelItem.Fields["ComponentName"];
                        if (components != null && components.List != null && parentItem != null && parentItem.Fields["Content Type"] != null && !string.IsNullOrEmpty(parentItem.Fields["Content Type"].Value) && components.List.ToString().Contains(parentItem.Fields["Content Type"].Value))
                        {
                            sbItemId.Append("@@id='" + labelItem.ID + "'").Append(" or ");
                        }
                    }
                }
                if (IsPathOrGuid(fieldValue) && !SourceContainsDataSource())
                {
                    var sourceItem = ResolveItem(fieldValue);
                    if (sourceItem != null)
                    {
                        if (sbItemId.Length > 80)
                            base.Source = sbItemId.ToString().Remove(sbItemId.Length - 4, 4) + "]";
                        else
                            base.Source = string.Empty;
                        base.Value = SanitizeValues(sourceItem, parentItem, labelItems, Value);
                    }
                    hasValidSource = true;
                }
            }
            if (Sitecore.Context.ClientPage.IsEvent)
            {
                string str = Sitecore.Context.ClientPage.ClientRequest.Form[this.ID + "_value"];
                if (str != null)
                {
                    if (base.GetViewStateString("Value", string.Empty) != str)
                    {
                    }
                    base.SetViewStateString("Value", str);
                }
            }
            base.OnLoad(e);
        }

        /// 
       /// If they are not children of the item in DataSourceField, remove GUIDs from a list of selected values
        /// 
        private string SanitizeValues(Item sourceItem, Item parentItem, Item[] labelItems, string value)
        {
            var db = GetDatabase();
            if (value == null || String.IsNullOrEmpty(value.Trim())) return String.Empty;
            var ids = value.Split('|');
            var validItems = new List();
            Sitecore.Data.Fields.MultilistField components = null;
            for (int i = 0; i < ids.Length; i++)
            {
                var item = db.GetItem(new ID(ids[i]), Language.Parse(ItemLanguage));
                if (item != null && item.Axes.IsDescendantOf(sourceItem))
                {
                    foreach (Item labelItem in labelItems)
                    {
                        components = (Sitecore.Data.Fields.MultilistField)labelItem.Fields["ComponentName"];
                        if (components != null && labelItem != null && item != null && labelItem.ID.ToString() == item.ID.ToString() && components.List != null && parentItem != null && parentItem.Fields["Content Type"] != null && !string.IsNullOrEmpty(parentItem.Fields["Content Type"].Value) && components.List.ToString().Contains(parentItem.Fields["Content Type"].Value))
                        {
                            validItems.Add(item);
                        }
                    }
                }
            }
            return String.Join("|", validItems.ConvertAll((x) => x.ID.ToString()));
        }
        private bool SourceContainsDataSource()
        {
            return this.Source.ToLower().Trim().StartsWith("datasource=") || this.Source.ToLower().Contains("&datasource=");
        }
        /// 
        /// Gets 'DataSourceField' from Source query parameters
        /// 
        /// Field name used for DataSourceField
        private string GetDataSourceField()
        {
            return StringUtil.ExtractParameter("DataSourceField", Source).Trim().ToLower();
        }
        /// 
        /// Gets 'DataSource' value from Source query parameters
        /// 
        public new string DataSource { get { return StringUtil.ExtractParameter("DataSource", Source).Trim().ToLower(); } }
        /// 
        /// Returns the value of a field we're using as a Data Source.
        /// 
        /// fieldName is the field being used as a Data Source
        /// Value of the Data Source.
        private string GetSourceFromField(string fieldName)
        {
            if (String.IsNullOrEmpty(fieldName)) return String.Empty;

            Item item = CurrentItem();
            if (item == null) return String.Empty;

            Field field = item.Fields[fieldName];
            if (field == null) return String.Empty;

            string fieldValue = field.GetValue(true);
            if (fieldValue == null) return String.Empty;

            return fieldValue;
        }
        private Item CurrentItem()
        {
            return Sitecore.Context.ContentDatabase.GetItem(new ID(base.ItemID), Language.Parse(ItemLanguage));
        }
        private bool IsPathOrGuid(string fieldValue)
        {
            return Sitecore.Data.ID.IsID(fieldValue) || fieldValue.StartsWith("/", StringComparison.OrdinalIgnoreCase);
        }
        /// 
        /// Returns Item set in DataSourceField.  Takes string-guid or string-path.
        /// 
        /// string-guid or string-path or Item found in the field specified by DataSourceField
        /// Item
        private Item ResolveItem(string fieldSource)
        {
            var db = GetDatabase();
            Assert.ArgumentNotNull(db, "Database");
            if (db == null) return null;
            if (Sitecore.Data.ID.IsID(fieldSource))
                return db.GetItem(new ID(fieldSource),Language.Parse(ItemLanguage));
            if (fieldSource.StartsWith("/", StringComparison.OrdinalIgnoreCase))
                return db.GetItem(fieldSource, Language.Parse(ItemLanguage));
            return null;
        }
        private new Database GetDatabase()
        {
            return Sitecore.Context.ContentDatabase;
        }
        /// 
        /// Reads customdatasource from template. 
        /// From customdatasource, finds appsettingkey based on type selected from parent of current item
        /// Returns value of appsettingkey
        ///         
        /// string
        private string GetTypeIncludeTemplates()
        {
            Item item = CurrentItem().Parent;
            if (item != null)
            {
                string customControlParentFieldName = ConfigurationManager.AppSettings["CustomControlParentFieldName"];
                if (item.Fields[customControlParentFieldName] != null && !string.IsNullOrWhiteSpace(item.Fields[customControlParentFieldName].Value))
                {
                    string type = item.Fields[customControlParentFieldName].Value;
                    Item typeItem = ResolveItem(type);
                    if (typeItem != null)
                    {
                        string typeName = typeItem.Name;
                        string dataSource = StringUtil.ExtractParameter(CMSConstants.CustomDataSource, Source).Trim();
                        if (!string.IsNullOrWhiteSpace(dataSource))
                        {
                            List typeDataSources = new List();
                            typeDataSources = dataSource.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            if (typeDataSources != null && typeDataSources.Count() > 0)
                            {
                                foreach (string typeSource in typeDataSources)
                                {
                                    if (typeSource.ToLower().Contains(typeName.ToLower()))
                                    {
                                        string appSettingKey = typeSource.ToLower().Replace(typeName.ToLower() + ":", string.Empty);
                                        if (!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings[appSettingKey]))
                                            return ConfigurationManager.AppSettings[appSettingKey];
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return string.Empty;
        }
    }
}
  
 
4. Custom TreeList
  
using System;
using System.Collections.Generic;
using System.Web.UI;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Shell.Applications.ContentEditor;
using System.Linq;
using System.Configuration;
using SitecoreCustom.Web.Extensions.Constants;
using System.Web;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    public class CustomTreeList : TreeList
    {
        private bool hasValidSource;
        public CustomTreeList()
        {
            Class = base.Class + " ftFieldTreeListExtended";
            base.Activation = true;
        }
        public new string Source { get; set; }
        public static bool HasSourceChanged = false;
        protected override void DoRender(HtmlTextWriter output)
        {
            if (hasValidSource)
            {
                base.DoRender(output);
                return;
            }
        }
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.ServerProperties["Value"] = this.ServerProperties["Value"];
        }
        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                base.Source = this.Source;
                var fieldValue = ConfigurationManager.AppSettings["ContentItemGUID"];
                var includeTemplates = HttpUtility.HtmlDecode(GetTypeIncludeTemplates());
                if (IsPathOrGuid(fieldValue) && !SourceContainsDataSource())
                {
                    var sourceItem = ResolveItem(fieldValue);
                    if (sourceItem != null)
                    {
                        base.Source = String.Format("{0}&DataSource={1}&{2}", Source, sourceItem.Paths.Path,includeTemplates);
                        this.Value = SanitizeValues(sourceItem, Value);
                    }
                    hasValidSource = true;
                    SetModified();
                }
            }
            if (Sitecore.Context.ClientPage.IsEvent)
            {
                string str = Sitecore.Context.ClientPage.ClientRequest.Form[this.ID + "_value"];
                if (str != null)
                {
                    if (base.GetViewStateString("Value", string.Empty) != str)
                    {
                        TreeList.SetModified();
                    }
                    base.SetViewStateString("Value", str);
                }
            }
            base.OnLoad(e);
        }
        private string SanitizeValues(Item sourceItem, string value)
        {
            var db = GetDatabase();
            if (value == null || String.IsNullOrEmpty(value.Trim())) return String.Empty;
            var ids = value.Split('|');
            var validItems = new List();
            for (int i = 0; i < ids.Length; i++)
            {
                var item = db.GetItem(new ID(ids[i]));
                if (item.Axes.IsDescendantOf(sourceItem))
                    validItems.Add(item);
            }
            return String.Join("|", validItems.ConvertAll((x) => x.ID.ToString()));
        }
        private bool SourceContainsDataSource()
        {
            return this.Source.ToLower().Trim().StartsWith("datasource=") || this.Source.ToLower().Contains("&datasource=");
        }
        private string GetDataSourceField()
        {
            return StringUtil.ExtractParameter("DataSourceField", Source).Trim().ToLower();
        }
        public new string DataSource { get { return StringUtil.ExtractParameter("DataSource", Source).Trim().ToLower(); } }
		
        private string GetSourceFromField(string fieldName)
        {
            if (String.IsNullOrEmpty(fieldName)) return String.Empty;
            Item item = CurrentItem();
            if (item == null) return String.Empty;
            Field field = item.Fields[fieldName];
            if (field == null) return String.Empty;
            string fieldValue = field.GetValue(true);
            if (fieldValue == null) return String.Empty;
            return fieldValue;
        }

        private Item CurrentItem()
        {
            return Sitecore.Context.ContentDatabase.GetItem(new ID(base.ItemID));
        }

        private bool IsPathOrGuid(string fieldValue)
        {
            return Sitecore.Data.ID.IsID(fieldValue) || fieldValue.StartsWith("/", StringComparison.OrdinalIgnoreCase);
        }
        private Item ResolveItem(string fieldSource)
        {
            var db = GetDatabase();
            Assert.ArgumentNotNull(db, "Database");
            if (db == null) return null;
            if (Sitecore.Data.ID.IsID(fieldSource))
                return db.GetItem(new ID(fieldSource));
            if (fieldSource.StartsWith("/", StringComparison.OrdinalIgnoreCase))
                return db.GetItem(fieldSource);
            return null;
        }
        private new Database GetDatabase()
        {
            return Sitecore.Context.ContentDatabase;
        }
        private string GetTypeIncludeTemplates()
        {
            Item item = CurrentItem().Parent;
            if (item != null)
            {
                string customControlParentFieldName = ConfigurationManager.AppSettings["CustomControlParentFieldName"];
                if (item.Fields[customControlParentFieldName] != null && !string.IsNullOrWhiteSpace(item.Fields[customControlParentFieldName].Value))
                {
                    string type = item.Fields[customControlParentFieldName].Value;
                    Item typeItem = ResolveItem(type);
                    if (typeItem != null)
                    {
                        string typeName = typeItem.Name;
                        string dataSource = StringUtil.ExtractParameter(CMSConstants.CustomDataSource, Source).Trim();
                        if (!string.IsNullOrWhiteSpace(dataSource))
                        {
                            List typeDataSources = new List();
                            typeDataSources = dataSource.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            if (typeDataSources != null && typeDataSources.Count() > 0)
                            {
                                foreach (string typeSource in typeDataSources)
                                {
                                    if (typeSource.ToLower().Contains(typeName.ToLower()))
                                    {
                                        string appSettingKey = typeSource.ToLower().Replace(typeName.ToLower() + ":", string.Empty);
                                        if (!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings[appSettingKey]))
                                            return ConfigurationManager.AppSettings[appSettingKey];
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return string.Empty;
        }
    }
}

5. Custom Required Field Validator
  
using Sitecore.Data.Validators;
using System;
using System.Runtime.Serialization;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    [Serializable]
    public class CustomRequiredFieldValidator : StandardValidator
    {
        public override string Name
        {
            get
            {
                return "Required";
            }
        }
        public CustomRequiredFieldValidator():base()
        {
        }
        public CustomRequiredFieldValidator(SerializationInfo info, StreamingContext context):base(info, context)
        {
        }
        protected override ValidatorResult Evaluate()
        {
            if (!string.IsNullOrEmpty(this.ControlValidationValue))
                return ValidatorResult.Valid;
            this.Text = this.GetText("Field \"{0}\" must contain a value.", this.GetFieldDisplayName());
            return this.GetFailedResult(ValidatorResult.FatalError);
        }
        protected override ValidatorResult GetMaxValidatorResult()
        {
            return this.GetFailedResult(ValidatorResult.FatalError);
        }
    }
}

These custom code files can also be downloaded from here

Comments

Popular posts from this blog

Steps to create a Sitecore JSS app and Deploy to Sitecore

If you are a beginner in Sitecore JSS and you are looking step-by-step by process to setup your first JSS App with Sitecore, please proceed further and setup up your first JSS App along with deploying it to Sitecore. Before we jump start creating JSS APP, let us start with a quick introduction to Sitecore JSS. What is Sitecore JSS?  Sitecore JavaScript Services (JSS) is a complete SDK for JavaScript developers that enables you to build full-fledged solutions using Sitecore and modern JavaScript UI libraries and frameworks. Build Headless JavaScript applications with the power of Sitecore. Use your favorite JavaScript framework powered by an enterprise experience platform like React, Angular or Vue.js. Prerequisites for Connected mode with Sitecore Required Installations node.js v6.9 or later npm v5.7 or later Sitecore 9 or later installation with JSS(For JSS component ref, https://dev.sitecore.net/Downloads/Sitecore_JavaScript_Services.aspx) Required Settings  Sitecore

Sitecore JSS - Custom Rendering Content Resolvers

In Sitecore, while working for real-time projects, you may get scenarios where you would see a need to customize you rendering output to serialze. Sitecore provides three different ways of customizing your rendering output with Sitecore JSS. They are as below. • Use JSS GraphQL Support - Using Integrated GraphQL queries • Use Out-of-the-box Rendering Content Resolvers - Using Sitecore JSS built-in Rendering Content Resolvers • Implementing a Custom Rendering Content Resolvers by inheriting RenderingContentsResolver Why Customization? In Sitecore development, many times we encounter scenarios to deal with hierarchical item structures like multi-level menu, product category, product sub-category, product details, forms etc., and even, in case where there is a need to combine the Sitecore data with any non-Sitecore data. In these types, Sitecore JSS is not able to serialize item structures with sub-hierarchies into JSON. Sitecore Jss allow us custiomize in