Skip to main content

SharePoint Gridview Multi Column filtering and sorting.

SharePoint OOTB grid view allows us to perform multiple filtering and sorting. But when you create a custom solution with SPGridview then implementing multi column filter and sorting is a bit tricky. After a good amount of goggling I found two reliable solutions.
Below are two links that helped me as solution.


I used 2nd link in my solution. Let’s implement an example. Add below code to your designer page. Lets start creating an demo.
1.      Create a new SharePoint Project.
2.      Add a visual webpart into it.



3.      Add html code to create SPGridview.(you can take below code as well)
<SharePoint:SPGridView runat="server" ID="gvDemo" AutoGenerateColumns="false" DataSourceID="gridds"
    AllowFiltering="true" AllowSorting="true" FilteredDataSourcePropertyName="FilterExpression"
    HeaderStyle-HorizontalAlign="Left" EnableTheming="true" OnSorting="gvDemo_Sorting" OnRowDataBound="gvDemo_RowDataBound" EnableViewState="false"
    PagerSettings-Position="Bottom" ShowHeader="true">
    <Columns>
        <asp:BoundField HeaderText="Title" DataField="Title" SortExpression="Title" />
        <asp:BoundField HeaderText="Field1" DataField="Field1" SortExpression="Field1" />
        <asp:BoundField HeaderText="Field2" DataField="Field2" SortExpression="Field2" />
        <asp:BoundField HeaderText="Field3" DataField="Field3" SortExpression="Field3" />
    </Columns>
</SharePoint:SPGridView>
<asp:ObjectDataSource ID="gridds" runat="server" OnObjectCreating="gridds_ObjectCreating" EnableViewState="false"
    SelectMethod="GetDataSourceApprove" ></asp:ObjectDataSource>


We need to create a set of properties like below, this properties contain code that will handle viewstate values of filter and sort expressions.
#region Properties
        private char[] _sortingSeparator = { ',' };
        private string[] _filterSeparator = { "AND" };
        private const string AppViewStateFilterExp = "ApproveFilterExpression";
        private const string AppViewStateSortExp = "ApproveSortExpression";
        private const string ApproveGridViewID = "gvDemo";
        private const string FilteredDataSourcePropertyName = "FilterExpression";
        private const string FilteredDataSourcePropertyFormat = "convert({1}, 'System.String') like '{0}'";
        private static string CallBackGridID;
        private static string CallBackGridParam;
        private const string FilterDataFields = "Title,Field1,Field2,Field3";
        string FilterExpressionApprove
        {
            get
            {
                if (ViewState[AppViewStateFilterExp] == null)
                { ViewState[AppViewStateFilterExp] = ""; }

                return (string)ViewState[AppViewStateFilterExp];
            }
            set
            {
                string thisFilterExpression = "(" + value.ToString() + ")";
                List<string> fullFilterExpression = new List<string>();

                if (ViewState[AppViewStateFilterExp] != null)
                {
                    string[] fullFilterExp = ViewState[AppViewStateFilterExp].ToString().Split(_filterSeparator, StringSplitOptions.RemoveEmptyEntries);
                    fullFilterExpression.AddRange(fullFilterExp);

                    //if the filter is gone expression already exist?
                    int index = fullFilterExpression.FindIndex(s => s.Contains(thisFilterExpression));
                    if (index == -1)
                    { fullFilterExpression.Add(thisFilterExpression); }
                }
                else
                {
                    fullFilterExpression.Add(thisFilterExpression);
                }
                //Create final Filter expression
                string filterExp = string.Empty;
                filterExp = string.Join(" AND ", fullFilterExpression.ToArray());
                ViewState[AppViewStateFilterExp] = filterExp;
            }
        }

        string SortExpressionApprove
        {
            get
            {
                if (ViewState[AppViewStateSortExp] == null)
                { ViewState[AppViewStateSortExp] = ""; }

                return (string)ViewState[AppViewStateSortExp];
            }
            set
            {
                string[] thisSE = value.ToString().Split(' ');
                string thisSortExpression = thisSE[0];
                List<string> fullSortExpression = new List<string>();

                if (ViewState[AppViewStateSortExp] != null)
                {
                    string[] fullSortExp = ViewState[AppViewStateSortExp].ToString().Split(_sortingSeparator);
                    fullSortExpression.AddRange(fullSortExp);

                    //does the sort expression already exist?
                    int index = fullSortExpression.FindIndex(s => s.Contains(thisSortExpression));
                    if (index >= 0)
                    {
                        string s = string.Empty;
                        if (value.ToString().Contains("DESC"))
                        { s = value.ToString(); }
                        else
                        {
                            s = fullSortExpression[index];
                            if (s.Contains("ASC"))
                            { s = s.Replace("ASC", "DESC"); }
                            else
                            { s = s.Replace("DESC", "ASC"); }
                        }
                        //reset the sort direction
                        fullSortExpression[index] = s;
                    }
                    else
                    {
                        if (value.ToString().Contains("DESC"))
                        { fullSortExpression.Add(value.ToString()); }
                        else
                        { fullSortExpression.Add(thisSortExpression + " ASC"); }
                    }
                }
                else
                {
                    if (value.ToString().Contains("DESC"))
                    { fullSortExpression.Add(value.ToString()); }
                    else
                    { fullSortExpression.Add(thisSortExpression + " ASC"); }
                }

                //loop through the list<T> and serialize to string
                string sortExp = string.Empty;
                fullSortExpression.ForEach(s => sortExp += s);
                sortExp = sortExp.Replace(" ASC", " ASC,");
                sortExp = sortExp.Replace(" DESC", " DESC,");
                ViewState[AppViewStateSortExp] = sortExp.Remove(sortExp.LastIndexOf(','));
            }
        }

        #endregion

Now we need to add a Javascript file that will handle images that are to be shows as when user applies filter and sorting. You can place javascript file in Layouts folder like below.



That’s it now just loads script in page load method like below.
ScriptLink.Register(this.Page, "/_layouts/MultiColumnFilterGridViewDemo/Custom_spgridview.js", false);

We have replaces default Select Method of Object Data Source from “SelectGridData” to “GetDataSourceApprove” .
protected void Page_Load(object sender, EventArgs e)
        {
            gridds.FilterExpression = FilterExpressionApprove;
           
            ScriptLink.Register(this.Page, "/_layouts/MultiColumnFilterGridViewDemo/Custom_spgridview.js", false);
            //pass the SortExpression to the select method
            gridds.SortParameterName = "SortExpression";

            //Nice (!important) -> this resets the dropdown options for other columns after a filter is selected
            gridds.FilterExpression = FilterExpressionApprove;

            gvDemo.FilterDataFields = FilterDataFields;
            gvDemo.FilteredDataSourcePropertyFormat = FilteredDataSourcePropertyFormat;

            gridds.TypeName = this.GetType().AssemblyQualifiedName;
            gvDemo.DataSourceID = gridds.ID;
            gvDemo.DataBind();
        }

        protected void gvDemo_Sorting(object sender, System.Web.UI.WebControls.GridViewSortEventArgs e)
        {
            string sDir = e.SortDirection.ToString();
            sDir = sDir == "Descending" ? " DESC" : "";

            SortExpressionApprove = e.SortExpression + sDir;
            e.SortExpression = SortExpressionApprove;

            //keep the filter
            if (!string.IsNullOrEmpty(FilterExpressionApprove))
                gridds.FilterExpression = FilterExpressionApprove;
        }

        protected void gridds_ObjectCreating(object sender, System.Web.UI.WebControls.ObjectDataSourceEventArgs e)
        {
            e.ObjectInstance = this;
        }
        //function to clean the Filter Set already.
        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);

            //set call back
            HttpRequest oRequest = HttpContext.Current.Request;
            if (oRequest.Form["__CALLBACKID"] != null)
                CallBackGridID = oRequest.Form["__CALLBACKID"].ToString();

            //Enable icon for correct column
            if (oRequest.Form["__CALLBACKPARAM"] != null)
                CallBackGridParam = oRequest.Form["__CALLBACKPARAM"].ToString().Replace("__SPGridView__;", "");

            //Clear Filter code
            if (Context.Request.Form["__EVENTARGUMENT"] != null &&
                Context.Request.Form["__EVENTARGUMENT"].Contains("__ClearFilter__") &&
                CallBackGridID.Contains(gvDemo.ID) &&
                ViewState[AppViewStateFilterExp] != null)
            {
                List<string> finalFilterExpression = new List<string>();

                string[] seperatorHere = { " AND " };
                string[] currentFilterExp = ViewState[AppViewStateFilterExp].ToString().Split(seperatorHere, StringSplitOptions.RemoveEmptyEntries);

                //code to remove the filter only from the particular column
                foreach (string exp in currentFilterExp)
                {
                    if (!exp.Contains(CallBackGridParam))
                        finalFilterExpression.Add(exp);
                }

                ViewState.Remove(AppViewStateFilterExp);
                ViewState[AppViewStateFilterExp] = String.Join(" AND ", finalFilterExpression.ToArray());
            }
        }
        protected void gvDemo_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
        {
            if (sender == null || e.Row.RowType != DataControlRowType.Header)
            { return; }

            SPGridView grid = sender as SPGridView;

            // Show icon on filtered and sorted columns
            for (int i = 0; i < grid.Columns.Count; i++)
            {
                DataControlField field = grid.Columns[i];

                //Necessary
                if (String.IsNullOrEmpty(field.SortExpression))
                    continue;

                if (FilterExpressionApprove.Contains(field.SortExpression) &&
                    !string.IsNullOrEmpty(FilterExpressionApprove))
                {
                    PlaceHolder panel = HeaderImages(field, "/_layouts/images/filter.gif");
                    e.Row.Cells[i].Controls[0].Controls.Add(panel);
                }
                else if (SortExpressionApprove.Contains(field.SortExpression))
                {
                    string url = sortImage(field);
                    PlaceHolder panel = HeaderImages(field, url);
                    e.Row.Cells[i].Controls[0].Controls.Add(panel);
                }
            }
        }
        private PlaceHolder HeaderImages(DataControlField field, string imageUrl)
        {
            Image filterIcon = new Image();
            filterIcon.ImageUrl = imageUrl;
            filterIcon.Style[HtmlTextWriterStyle.MarginLeft] = "2px";

            Literal headerText = new Literal();
            headerText.Text = field.HeaderText;

            PlaceHolder panel = new PlaceHolder();
            panel.Controls.Add(headerText);

            //add the sort icon if needed
            if (FilterExpressionApprove.Contains(field.SortExpression) &&
                SortExpressionApprove.Contains(field.SortExpression))
            {
                string url = sortImage(field);
                Image sortIcon = new Image();
                sortIcon.ImageUrl = url;
                sortIcon.Style[HtmlTextWriterStyle.MarginLeft] = "1px";
                panel.Controls.Add(sortIcon);
                //change the left margin to 1
                filterIcon.Style[HtmlTextWriterStyle.MarginLeft] = "1px";
            }

            panel.Controls.Add(filterIcon);
            return panel;
        }

        private string sortImage(DataControlField field)
        {
            string url = string.Empty;
            string[] fullSortExp = SortExpressionApprove.Split(_sortingSeparator);
            List<string> fullSortExpression = new List<string>();
            fullSortExpression.AddRange(fullSortExp);

            //does the sort expression already exist?
            int index = fullSortExpression.FindIndex(s => s.Contains(field.SortExpression));
            if (index >= 0)
            {
                string s = fullSortExpression[index];
                if (s.Contains("ASC"))
                { url = "_layouts/images/sortup.gif"; }
                else
                { url = "_layouts/images/sortdown.gif"; }
            }
            return url;
        }

        void buildFilterView(string filterExp)
        {
            string lastExp = filterExp;
            if (lastExp.Contains("AND"))
            {
                if (lastExp.Length < lastExp.LastIndexOf("AND") + 4)
                { lastExp = lastExp.Substring(lastExp.LastIndexOf("AND") + 4); }
                else
                { lastExp = string.Empty; }
            }

            //update the filter
            if (!string.IsNullOrEmpty(lastExp))
            { FilterExpressionApprove = lastExp; }

            //reset object dataset filter
            if (!string.IsNullOrEmpty(FilterExpressionApprove))
            { gridds.FilterExpression = FilterExpressionApprove; }

            //set the filterFieldName parameter with multi value ";;;;" used in the JsCode
            if (!string.IsNullOrEmpty(FilterExpressionApprove))
                setFilterFiledNameAttribute(FilterExpressionApprove, _filterSeparator, gvDemo);
        }

        public DataTable GetDataSourceApprove(string SortExpression)
        {
            DataTable dt = new DataTable();
            // To Do:
            dt.Columns.Add("Title");
            dt.Columns.Add("Field1");
            dt.Columns.Add("Field2");
            dt.Columns.Add("Field3");

            DataRow dr;
            dr = dt.NewRow(); dr["Title"] = "A1"; dr["Field1"] = "B3"; dr["Field2"] = "C3"; dr["Field3"] = "D3"; dt.Rows.Add(dr);
            dr = dt.NewRow(); dr["Title"] = "A1"; dr["Field1"] = "B1"; dr["Field2"] = "C1"; dr["Field3"] = "D1"; dt.Rows.Add(dr);
            dr = dt.NewRow(); dr["Title"] = "A1"; dr["Field1"] = "B1"; dr["Field2"] = "C1"; dr["Field3"] = "D2"; dt.Rows.Add(dr);
            dr = dt.NewRow(); dr["Title"] = "A5"; dr["Field1"] = "B2"; dr["Field2"] = "C2"; dr["Field3"] = "D5"; dt.Rows.Add(dr);
            dr = dt.NewRow(); dr["Title"] = "A4"; dr["Field1"] = "B2"; dr["Field2"] = "C2"; dr["Field3"] = "D4"; dt.Rows.Add(dr);
            //Your Code to fill DataTable

            #region Custom Sorting on the DataTable
            //clean up the sort expression if needed - the sort descending
            //menu item causes the double in some cases
            //Please note: this SortExpression is local variable
            if (SortExpression.ToLowerInvariant().EndsWith("desc desc"))
                SortExpression = SortExpression.Substring(0, SortExpression.Length - 5);

            //need to handle the actual sorting of the data
            if (!string.IsNullOrEmpty(SortExpression))
            {
                if (!string.IsNullOrEmpty(CallBackGridID) && CallBackGridID.Contains(ApproveGridViewID) && FilterDataFields.Contains(SortExpression.Split(' ')[0].ToString()))
                {
                    DataView view = new DataView(dt);
                    view.Sort = SortExpression; //Local variable passed as parameter
                    DataTable newTable = view.ToTable();
                    dt.Clear();
                    dt = newTable;
                }
                else
                {
                    DataView view = new DataView(dt);
                    view.Sort = SortExpressionApprove; //the property
                    DataTable newTable = view.ToTable();
                    dt.Clear();
                    dt = newTable;
                }
            }

            #endregion

            return dt;
        }

        private void setFilterFiledNameAttribute(string filterExpressionProperty, string[] filterSeperator, SPGridView objSPGrid)
        {
            //Set Filter Field Name
            if (!string.IsNullOrEmpty(filterExpressionProperty))
            {
                string[] filterFields = filterExpressionProperty.Split(filterSeperator, StringSplitOptions.RemoveEmptyEntries);
                List<string> filterFiledNamesString = new List<string>();

                foreach (string filterField in filterFields)
                {
                    if (filterField.Split('=')[0] != null)
                    {
                        string tmpStr = filterField.Split('=')[0].ToString();
                        if (tmpStr.Contains("(")) tmpStr = tmpStr.Replace("(", "");
                        if (tmpStr.Contains(")")) tmpStr = tmpStr.Replace(")", "");
                        if (tmpStr.Contains("((")) tmpStr = tmpStr.Replace("((", "");
                        if (tmpStr.Contains("))")) tmpStr = tmpStr.Replace("))", "");
                        tmpStr = tmpStr.Trim();
                        if (!string.IsNullOrEmpty(tmpStr)) filterFiledNamesString.Add(tmpStr);
                    }
                }
                if (filterFiledNamesString.Count > 0)
                    objSPGrid.Attributes["FilterFieldName"] = string.Join(";", filterFiledNamesString.ToArray());
            }
        }


        protected override void OnPreRender(EventArgs e)
        {
            ScriptLink.Register(this.Page, "/_layouts/Multicolumnfilter-spgridview1/Custom_spgridview.js", false);

            if (!Page.IsPostBack)
                gvDemo.DataBind();

            //make sure the header images are set => Keep it here !important
            buildFilterView(gridds.FilterExpression);

            base.OnPreRender(e);
        }

        protected override void Render(HtmlTextWriter writer)
        {
            gvDemo.Attributes["callbackEventReference"] = gvDemo.Attributes["callbackEventReference"].Replace("SPGridView_FilterCallbackHandler", "Custom_SPGridView_FilterCallbackHandler");

            #region Microsoft Fix
            try
            {
                if (gvDemo.HeaderRow != null)
                {
                    if
                   (gvDemo.HeaderRow.Controls[0].Controls.Count > 0 && gvDemo.HeaderRow.Controls[0].Controls[0].GetType().Equals(typeof(Microsoft.SharePoint.WebControls.Menu)))
                    {
                        Microsoft.SharePoint.WebControls.Menu menu = (Microsoft.SharePoint.WebControls.Menu)gvDemo.HeaderRow.Controls[0].Controls[0];
                        menu.ClientOnClickPreMenuOpen =
                          "Custom_SPGridView_FilterPreMenuOpen('" +
                          gvDemo.ClientID + "','" + gvDemo.ClientID +
                          "_SPGridViewFilterMenuTemplate', '" + menu.ClientID + "', 'Title', event);" +
                          " MMU_Open(byid('" + gvDemo.ClientID + "_SPGridViewFilterMenuTemplate')," +
                          " MMU_GetMenuFromClientId('" + menu.ClientID + "'),event,true,null,0); return;";
                        //Custom_SPGridView_FilterPreMenuOpen(gridViewClientId, templateClientId, menuClientId, dataFieldName, e)
                    }
                    if
                   (gvDemo.HeaderRow.Controls[1].Controls.Count > 0 && gvDemo.HeaderRow.Controls[1].Controls[0].GetType().Equals(typeof(Microsoft.SharePoint.WebControls.Menu)))
                    {

                        Microsoft.SharePoint.WebControls.Menu menu = (Microsoft.SharePoint.WebControls.Menu)gvDemo.HeaderRow.Controls[1].Controls[0];
                        menu.ClientOnClickPreMenuOpen =
                            "Custom_SPGridView_FilterPreMenuOpen('" +
                            gvDemo.ClientID + "','" + gvDemo.ClientID +
                            "_SPGridViewFilterMenuTemplate', '" + menu.ClientID + "', 'Field1', event);" +
                            " MMU_Open(byid('" + gvDemo.ClientID + "_SPGridViewFilterMenuTemplate')," +
                            " MMU_GetMenuFromClientId('" + menu.ClientID + "'),event,true,null,0); return;";
                    }
                    if
                   (gvDemo.HeaderRow.Controls[2].Controls.Count > 0 && gvDemo.HeaderRow.Controls[2].Controls[0].GetType().Equals(typeof(Microsoft.SharePoint.WebControls.Menu)))
                    {

                        Microsoft.SharePoint.WebControls.Menu menu = (Microsoft.SharePoint.WebControls.Menu)gvDemo.HeaderRow.Controls[2].Controls[0];
                        menu.ClientOnClickPreMenuOpen =
                    "Custom_SPGridView_FilterPreMenuOpen('" +
                    gvDemo.ClientID + "','" + gvDemo.ClientID +
                    "_SPGridViewFilterMenuTemplate', '" + menu.ClientID + "', 'Field2', event);" +
                    " MMU_Open(byid('" + gvDemo.ClientID + "_SPGridViewFilterMenuTemplate')," +
                    " MMU_GetMenuFromClientId('" + menu.ClientID + "'),event,true,null,0); return;";

                    }
                    if
                   (gvDemo.HeaderRow.Controls[3].Controls.Count > 0 && gvDemo.HeaderRow.Controls[3].Controls[0].GetType().Equals(typeof(Microsoft.SharePoint.WebControls.Menu)))
                    {

                        Microsoft.SharePoint.WebControls.Menu menu = (Microsoft.SharePoint.WebControls.Menu)gvDemo.HeaderRow.Controls[3].Controls[0];
                        menu.ClientOnClickPreMenuOpen =
                    "Custom_SPGridView_FilterPreMenuOpen('" +
                    gvDemo.ClientID + "','" + gvDemo.ClientID +
                    "_SPGridViewFilterMenuTemplate', '" + menu.ClientID + "', 'Field3', event);" +
                    " MMU_Open(byid('" + gvDemo.ClientID + "_SPGridViewFilterMenuTemplate')," +
                    " MMU_GetMenuFromClientId('" + menu.ClientID + "'),event,true,null,0); return;";

                    }
                }
            }
            catch (Exception ex)
            {
                //To Do
            }
            #endregion

            base.Render(writer);
        }

Below Is the code for java script that we included above
var KM_SPGridView_CallbackContext;
var enableCheckBox = false;

function KM_SPGridView_FilterPreMenuOpen(gridViewClientId, templateClientId, menuClientId, dataFieldName, e) { var gridView = document.getElementById(gridViewClientId), callbackEventReference = gridView.getAttribute("callbackEventReference"), callbackArgumentPrefix = gridView.getAttribute("callbackArgumentPrefix"), postbackEventReference = gridView.getAttribute("postbackEventReference"), filterFieldName = gridView.getAttribute("filterFieldName"), filterFieldValue = gridView.getAttribute("filterFieldValue"), filterCurrentlyOn = false; if (filterFieldName != null && filterFieldName.length > 0 && filterFieldName.match(dataFieldName) != null) { filterCurrentlyOn = true; enableCheckBox = true; } var menuTemplate = document.getElementById(templateClientId), menuLink = document.getElementById(menuClientId); if (menuLink.getAttribute("suppressBubbleIfPostback") != null && e != null && e.srcElement != null && e.srcElement.href != null && e.srcElement.href.substr(0, MMU_postbackPrefix.length) == MMU_postbackPrefix) { event.cancelBubble = true; return } SPGridView_FixupFilterValuesFromMenuTemplate(menuTemplate, filterCurrentlyOn); var menuItem = CAMOpt(menuTemplate, Strings.STS.L_Loading_Text, "null"); menuItem.setAttribute("isFilterItem", "true"); menuItem.setAttribute("enabled", "false"); KM_SPGridView_CallbackContext = {}; KM_SPGridView_CallbackContext.gridViewClientId = gridViewClientId; KM_SPGridView_CallbackContext.templateClientId = templateClientId; KM_SPGridView_CallbackContext.menuClientId = menuClientId; KM_SPGridView_CallbackContext.dataFieldName = dataFieldName; callbackEventReference = callbackEventReference.replace(/__CALLBACKARGUMENT__/g, dataFieldName); callbackEventReference = callbackEventReference.replace(/__CALLBACKCONTEXT__/g, gridViewClientId + ";" + templateClientId + ";" + menuClientId + ";" + dataFieldName); eval(callbackEventReference) }

function KM_SPGridView_FilterCallbackHandler(q, p) { var a = p.split(";"); if (a.length != 4) { alert("ERROR: SPGridView_FilterCallbackHandler() - values.length != 4"); return } var m = a[0], n = a[1], o = a[2], i = a[3], c = document.getElementById(m); if (c == null) { alert("ERROR: SPGridView_FilterCallbackHandler() - gridView == null"); return } var b = document.getElementById(n); if (b == null) { alert("ERROR: SPGridView_FilterCallbackHandler() - menuTemplate == null"); return } var k = document.getElementById(o); if (k == null) { alert("ERROR: SPGridView_FilterCallbackHandler() - menu == null"); return } var d = c.getAttribute("postbackEventReference"); if (d == null || d.length <= 0) { alert("ERROR: SPGridView_FilterCallbackHandler() - postbackEventReference is null or empty"); return } var e = c.getAttribute("filterFieldName"), l = c.getAttribute("filterFieldValue"), h = false; if (e != null && e.length > 0 && e.match(i) != null) h = true; SPGridView_FixupFilterValuesFromMenuTemplate(b, h); a = q.split(";"); for (var f = 0; f < a.length; f++) { var g = unescape(a[f]), r = d.replace(/__POSTBACKARGUMENT__/g, i + ";" + g.replace(/\\/g, "\\\\").replace(/\'/g, "\\'").replace(/%/g, "%25").replace(/;/g, "%3b")), j = CAMOpt(b, g, r); j.setAttribute("isFilterItem", "true"); enableCheckBox && j.setAttribute("checked", "true"); enableCheckBox = false; } HideMenu(b); MMU_Open(b, k); popUpHandler() }

function popUpHandler() {

    //Put "(Empty)" in popup Menu
    var menuTxt = $('ul.ms-core-menu-list li:eq(5)').attr('text');
    if ($.trim(menuTxt) == "") {
        $('ul.ms-core-menu-list li:eq(5) span.ms-core-menu-title').text("(Empty)");
    }
}

Below is the output for above example.





Thanks & Regards,

Keyur Pandya

Comments

Popular posts from this blog

Identity client runtime library (IDCRL) did not get a response from the login server.

Recently I was doing some testing with a background PowerShell and encountered a weird error. “Identity client runtime library (IDCRL) did not get a response from the login server”. The error that you might encounter while working with PowerShell. This error is very misleading when it comes to identifying what could go wrong. After doing quite a good amount of research below are the probable causes for the error. Invalid Credentials MFA (Multi-Factor Authentication) Manage security defaults. Solutions Invalid Credentials Check if your credentials are wrong. Especially if you are using variables. MFA (Multi-Factor Authentication) Check if MFA is enabled on the account which you are using. These only affect you badly if you are developing PowerShell for a background Job. Go to Microsoft 365 admin center Users -> Active users -> Select the user -> Manage multifactor authentication -> Select the user -> Disable multi-factor authentication. M...

Business Data Connectivity

I came to a requirement wherein I was supposed to get data from an 3 rd party portal using API’s and then bring them to SharePoint server. The first approach that I finalized was just to make BDC solution that will get data from 3 rd party portal and will deploy it to SharePoint. How to Create BDC solution in SharePoint? I found below link that is having really great description about hot to create and deploy the BDC solution to SharePoint. http://www.c-sharpcorner.com/uploadfile/hung123/creating-business-data-connectivity-service-using-visual-studio-2010/ After creating an POC I came to know that BDC model cannot be deployed on Multi tenant farm. So what can be done next? After some amount of googling I came to know that we can create BDC solution using WCF services also. So I created a WCF service solution that acted as a wrapper that used to fetch data from the portal. We can them publish that service to IIS or Server and use the servic...

Site Design Tasks, Power Automate and Modern Sites

S harePoint Site templates are now replaced with Site designs in Modern Sites. We can create custom site designs using some json script(s). Site Design allows to create lists, create list views, apply theme, customize navigation, create content types, create site columns and so on. Click here to see JSON scheme reference for creating custom site design.  Endpoint to apply site design as a part of flow is as below. _api/Microsoft.Sharepoint.Utilities.WebTemplateExtensions.SiteScriptUtility.AddSiteDesignTaskToCurrentWeb We must use “Send Http Request to SharePoint” action to make an API call to SharePoint. SiteDesignId must be part if body, this is GUID of the SharePoint site design you need to apply. We can line up sequence of calls if we need to apply multiple site designs to a single site. We can now wait for few mins and all our sited designs will get applied or we can also check the status by making another API call with below endpoint. You just need to pass the Apply Desig...