How to: Enable Sorting in a JS Grid Control

Applies to: SharePoint Foundation 2010

This how-to demonstrates how to enable sorting on a basic JS Grid control. This how-to builds on the How to: Create a Basic JS Grid Control topic, and assumes that you've created a basic JS Grid control as outlined in that topic.

Prerequisites

Creating a sortable grid

Creating a sortable grid involves the following steps:

  1. Enabling sort behavior on columns

  2. Using a JS Grid delegate to handle the sort in ECMAScript (JavaScript, JScript)

  3. Writing a callback function to sort the data and rebind the grid

To enable sorting with IsSortable property

  1. Open the JSGrid solution you created in the previous how-to.

  2. Open GridUtilities.cs.

  3. In GetGridColumns method, set the GridColumn.IsSortable property to true.

    To make specific columns sortable, use conditional statements on the column name, which is unique.

    The code should appear as follows.

    public static IList<GridColumn> GetGridColumns(DataTable table)
    {
        List<GridColumn> r = new List<GridColumn>();
        foreach (DataColumn iterator in table.Columns)
        {
            /* Columns are visible in the grid; we don't want these
                as grid columns. */
            // HierarchyParentKey is used in the How to: Create a Hierarchy Grid topic.
    
            if (iterator.ColumnName != "Key"
                    && iterator.ColumnName != GridSerializer.DefaultGridRowStyleIdColumnName
                //&& iterator.ColumnName != GridSerializer.DefaultGanttBarStyleIdsColumnName // uncomment for the Create a Gantt Chart Using JS Grid How-To.
                    && iterator.ColumnName != "HierarchyParentKey"
                    && iterator.ColumnName.Substring(0, 5) != "costq"
                    && iterator.ColumnName.Substring(0, 5) != "Quart")
            {
                GridColumn col = new GridColumn();
                // Point the column at a fieldKey name.
                col.FieldKey = iterator.ColumnName;
                // Give the column header a name.
                col.Name = iterator.ColumnName;
                // Define the column width.
                col.Width = 210;
                // Enable sorting for the column
                col.IsSortable = true;
    
                // Define column settings.
                if (iterator.ColumnName == "Department")
                {
                    col.IsHidable = false;
                }
                if (iterator.ColumnName == "Yearly Estimate")
                {
                    col.IsSortable = true;
                }
    
                // Add the column.
                r.Add(col);
            }
        }
        return r;
    }
    

    Note

    Note that IsSortable property is used to enable or disable sorting on Microsoft.SharePoint.JSGrid.GridColumn. The GridColumn.IsSortable property is set to false by default.

Using a JS Grid delegate to handle the sort

The JS Grid control supports a variety of delegates. The Sort delegate is used to handle sort on grid. For the list of delegates supported by the JS Grid control, refer to JS Grid Delegates.

To use the Sort delegate

  1. Open the JSGrid solution.

  2. Open JSGridWebPartUserControl.ascx.

  3. Add the following to the JavaScript code:

    • jsGridControl.SetDelegate(SP.JsGrid.DelegateType.Sort, HandleSort);

    • HandleSort method to handles the sort event and

    • DisplaySortedData method to rebind the sorted data back to grid

    Global level variables are added in order to maintain the sort, and store initial data source bound to grid, which can be reused to bind the grid after callback.

    The code should appear as follows.

    <SharePoint:JSGrid ID="_grid" runat="server" JSControllerClassName="GridManager"
        JSControllerInstanceName="GM" ShowLoadingIndicator="true" />
    <script type="text/javascript">
        Type.registerNamespace("GridManager");
        GridManager = function () {
    
            // Variables for the JSGrid control instance and the grid properties.
            var _jsGridControl;
            var _props;
    
            // Variables for sorting.
            var _orderByColumnName;
            var _isDescending;
    
            // Variable for the grid data source.
            var _tableCache;
    
            this.Init = function (jsGridControl, initialData, props) {
    
                // Assign it to global variable
                _jsGridControl = jsGridControl;
                _props = props;
    
                // Delegate to handle sort
                jsGridControl.SetDelegate(SP.JsGrid.DelegateType.Sort, HandleSort);
    
                var dataSource = new SP.JsGrid.StaticDataSource(initialData);
    
                // grid data source
                _tableCache = dataSource.tableCache;
                var jsGridParams = dataSource.InitJsGridParams();
                jsGridControl.Init(jsGridParams);
            }
    
            // HandleSort is called when the ascending/descending header dropdown is clicked.
            function HandleSort(newSortedCols) {
                _orderByColumnName = newSortedCols[0].columnName;
                _isDescending = newSortedCols[0].isDescending;
    
                // Disable the grid while it is being sorted.
                _jsGridControl.Disable();
    
                // Send the sorting values to the server by using a callback.
                var args = Sys.Serialization.JavaScriptSerializer.serialize({
                    OrderByColumnName: _orderByColumnName,
                    IsDescending: _isDescending
                });
    
                eval(_props.callbackScript);
            }
    
            // The DisplaySortedData function is called through the GridManager instance (named "GM").
            // Bind the sorted data to the JSGrid object, and show the grid again.
            this.DisplaySortedData = function (sortedData) {
                // Show the sorted data in the grid.
                if (sortedData && sortedData != '') {
                    var deserializedGridData = SP.JsGrid.Deserializer.DeserializeFromJson(sortedData);
                    var jsgridDeserializer = new SP.JsGrid.Deserializer(deserializedGridData, SP.JsGrid.DeserializationMode.RowView, _props.keyColumn);
                    _tableCache.Clear();
                    _tableCache.AddRawDataToCache(ConvertAssocArrayKeysToArray(jsgridDeserializer.data), jsgridDeserializer.data);
                    _jsGridControl.SetRowView(jsgridDeserializer.InitJsGridRowViewParams());
                    _jsGridControl.Enable();
                }
            }
    
            function ConvertAssocArrayKeysToArray(assocArray) {
                var r = [];
    
                for (var key in assocArray) {
                    r.push(key);
                }
    
                return r;
            }
        };
    </script>
    

    Note

    Note that the HandleSort method takes an array of objects as input from grid when the grid is sorted. The array contains the column name and the order (ascending or descending) in which it has to be sorted.

Disabling the grid during sorting

Optionally, the JS Grid control can be disabled during sorting, and enabled again after sorting, to prevent users from making changes to the grid while it is being sorted. The array of objects should be passed to the server using callback. The client argument has two properties: OrderByColumnName and IsDescending which should be passed server side, so add equivalent types in the server side.

To disable the grid during sorting

  1. In Solution Explorer, right-click the GridUtils folder, point to Add, and then click New Items.

  2. Select Visual C#, select Code, and then select Code File. Name the file CallbackArgs.cs.

  3. Copy the following code to the CallbackArgs.cs file.

    using System;
    public class CallbackArgs
    {
        public String OrderByColumnName;
        public bool IsDescending;
    }
    

Writing a callback to sort the data and rebind the grid

To enable a callback event on the server, implement the ICallbackEventHandler interface. The following implementation is specific to this topic.

To write a callback

  1. In the JSGrid solution, open JSGridWebPartUserControl.ascx.cs.

  2. Implement the ICallbackEventHandler interface for your partial class. Provide an implementation for the RaiseCallbackEvent and GetCallbackResult methods.

    RaiseCallbackEvent will be invoked from the client to perform the callback on the server. GetCallbackResult will return the callback result to the client.

  3. Add the following declarations.

    using System;
    using System.Data;
    using System.Web.Script.Serialization;
    using System.Web.UI;
    using JSGridSample.GridUtilityLib;
    using Microsoft.SharePoint.JSGrid;
    using Microsoft.SharePoint.JsonUtilities;
    
  4. Replace the contents of the JSGridWebPartUserControl class with the following.

    public partial class JSGridWebPartUserControl : UserControl, ICallbackEventHandler
    {
        private string KeyColumn = "Key";
    
        protected void Page_Load(object sender, EventArgs e)
        {
            // Build some simple data for the grid to display
            DataTable data = new GridData().Data(20);
    
            // Create a grid serializer to connect to data
            GridSerializer gds = new GridSerializer(
                SerializeMode.Full,
                data,
                KeyColumn,
                new FieldOrderCollection(new String[] { "Title" }),
                GridUtilities.GetGridFields(data),
                GridUtilities.GetGridColumns(data));
    
            // Set the grid serializer at the grid serializer data
            _grid.GridDataSerializer = gds;
    
            _grid.JsInitObject = new
            {
                callbackScript = this.Page.ClientScript.GetCallbackEventReference(
                    this,
                    "args",
                    "GM.DisplaySortedData",
                    "true",
                    true),
                keyColumn = KeyColumn
            };
        }
    
        #region Callback event
    
        private CallbackArgs _callbackArgs;
    
        public string GetCallbackResult()
        {
            // Build some simple data for the grid to display
            DataTable data = new GridData().Data(20);
    
            // Create a grid serializer to connect to data
            GridSerializer gds = new GridSerializer(
                SerializeMode.RowView,
                data,
                KeyColumn,
                new FieldOrderCollection(new[] { _callbackArgs.OrderByColumnName }, new[] { _callbackArgs.IsDescending }),
                GridUtilities.GetGridFields(data),
                GridUtilities.GetGridColumns(data));
    
            var serializer = new Serializer();
            return gds.ToJson(serializer);
        }
    
        // Raise a callback event.
        public void RaiseCallbackEvent(string eventArgument)
        {
            // Deserialize callback arguments from JSON
            _callbackArgs = new JavaScriptSerializer()
                .Deserialize<CallbackArgs>(eventArgument);
        }
    
        #endregion
    }
    

    To enable callbacks, the JS Grid control exposes the JsInitObject property, which can hold callback event reference.

    Note that in RaiseCallbackEvent, the argument from the client method HandleSort is type-casted to the server side equivalent type CallbackArgs. GetcallbackResult serializes the sorted data and returns to the client method DisplaySortedData (using callback event reference) in the form of JavaScript Object Notation (JSON). DisplaySortedData gets the sorted data, deserializes it and rebinds the grid. Do not forget to enable the grid if it is disabled while sorting.

To test the JS Grid sorting

  1. Run the project.

  2. Mouse over one of the column header. On the right side of the column you see a dropdown.

  3. On clicking the dropdown you can see two buttons generated Sort Ascending / Sort Descending.

  4. Click any one of them

  5. The grid will be refreshed with the sorted data.

See Also

Tasks

How to: Create a Basic JS Grid Control

Concepts

JS Grid Control

Features of the JS Grid Control

JS Grid Delegates