Skip to content
This repository has been archived by the owner on Jan 8, 2024. It is now read-only.

Commit

Permalink
Helper methods on column collection.
Browse files Browse the repository at this point in the history
Added helper methods and a ColumnCollection object to help you when
getting both filtered and sorted columns.

Improved sample code.
  • Loading branch information
ALMMa committed Mar 20, 2014
1 parent 0f65621 commit 2848fa2
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 40 deletions.
90 changes: 90 additions & 0 deletions DataTables.Mvc/ColumnCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#region Copyright
/* The MIT License (MIT)
Copyright (c) 2014 Anderson Luiz Mendes Matos
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#endregion Copyright
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataTables.Mvc
{
/// <summary>
/// Represents a read-only DataTables column collection.
/// </summary>
public class ColumnCollection : IEnumerable<Column>
{
/// <summary>
/// For internal use only.
/// Stores data.
/// </summary>
private IReadOnlyList<Column> Data;
/// <summary>
/// Created a new ReadOnlyColumnCollection with predefined data.
/// </summary>
/// <param name="columns">The column collection from DataTables.</param>
public ColumnCollection(IEnumerable<Column> columns)
{
if (columns == null) throw new ArgumentNullException("The provided column collection cannot be null", "columns");
Data = columns.ToList().AsReadOnly();
}
/// <summary>
/// Get sorted columns on client-side already on the same order as the client requested.
/// The method checks if the column is bound and if it's ordered on client-side.
/// </summary>
/// <returns>The ordered enumeration of sorted columns.</returns>
public IOrderedEnumerable<Column> GetSortedColumns()
{
return Data
.Where(_column => !String.IsNullOrWhiteSpace(_column.Data) && _column.IsOrdered)
.OrderBy(_c => _c.OrderNumber);
}
/// <summary>
/// Get filtered columns on client-side.
/// The method checks if the column is bound and if the search has a value.
/// </summary>
/// <returns>The enumeration of filtered columns.</returns>
public IEnumerable<Column> GetFilteredColumns()
{
return Data
.Where(_column => !String.IsNullOrWhiteSpace(_column.Data) && _column.Searchable && !String.IsNullOrWhiteSpace(_column.Search.Value));
}
/// <summary>
/// Returns the enumerable element as defined on IEnumerable.
/// </summary>
/// <returns>The enumerable elemento to iterate through data.</returns>
public IEnumerator<Column> GetEnumerator()
{
return Data.GetEnumerator();
}
/// <summary>
/// Returns the enumerable element as defined on IEnumerable.
/// </summary>
/// <returns>The enumerable element to iterate through data.</returns>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return ((System.Collections.IEnumerable)Data).GetEnumerator();
}
}
}
1 change: 1 addition & 0 deletions DataTables.Mvc/DataTables.Mvc.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
<Compile Include="IDataTablesRequest.cs" />
<Compile Include="NameValueCollectionExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ColumnCollection.cs" />
<Compile Include="Search.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
19 changes: 6 additions & 13 deletions DataTables.Mvc/DataTablesBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ public object BindModel(ControllerContext controllerContext, ModelBindingContext
ParseColumnOrdering(requestParameters, columns);

// Attach columns into the model.
model.AddColumns(columns);
model.SetColumns(columns);

// Returns the filled model.
return model;
return (IDataTablesRequest)model;
}
/// <summary>
/// Resolves the NameValueCollection from the request.
Expand Down Expand Up @@ -148,7 +148,7 @@ protected virtual List<Column> GetColumns(NameValueCollection collection)
{
try
{
var returnCollection = new List<Column>();
var columns = new List<Column>();

// Loop through every request parameter to avoid missing any DataTable column.
for (int i = 0; i < collection.Count; i++)
Expand All @@ -163,23 +163,16 @@ protected virtual List<Column> GetColumns(NameValueCollection collection)
var columnSearchValue = Get<string>(collection, String.Format(COLUMN_SEARCH_VALUE_FORMATTING, i));
var columnSearchRegex = Get<bool>(collection, String.Format(COLUMN_SEARCH_REGEX_FORMATTING, i));

var column = new Column(
columnData,
columnName,
columnSearchable,
columnOrderable,
columnSearchValue,
columnSearchRegex);

returnCollection.Add(column);
columns.Add(new Column(columnData, columnName, columnSearchable, columnOrderable, columnSearchValue, columnSearchRegex));
}
else break; // Stops iterating because there's no more columns.
}

return returnCollection;
return columns;
}
catch
{
// Returns an empty column collection to avoid null exceptions.
return new List<Column>();
}
}
Expand Down
34 changes: 28 additions & 6 deletions DataTables.Mvc/IDataTablesRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,44 @@ public interface IDataTablesRequest
/// <summary>
/// Gets the read-only collection of client-side columns with their options and configs.
/// </summary>
IReadOnlyCollection<Column> Columns { get; }
ColumnCollection Columns { get; }
}
/// <summary>
/// For internal use only.
/// Represents DataTables request parameters.
/// </summary>
class DataTablesRequest : IDataTablesRequest
{
/// <summary>
/// For internal use only.
/// Gets/Sets the draw counter from DataTables.
/// </summary>
public int Draw { get; set; }
/// <summary>
/// For internal use only.
/// Gets/Sets the start record number (jump) for paging.
/// </summary>
public int Start { get; set; }
/// <summary>
/// For internal use only.
/// Gets/Sets the length of the page (paging).
/// </summary>
public int Length { get; set; }
/// <summary>
/// For internal use only.
/// Gets/Sets the global search term.
/// </summary>
public Search Search { get; set; }
private List<Column> _Columns { get; set; }
public IReadOnlyCollection<Column> Columns { get { return _Columns.AsReadOnly(); } }
public DataTablesRequest() { _Columns = new List<Column>(); }
public void AddColumn(Column column) { _Columns.Add(column); }
public void AddColumns(IEnumerable<Column> columns) { _Columns.AddRange(columns); }
/// <summary>
/// For internal use only.
/// Gets/Sets the column collection.
/// </summary>
public ColumnCollection Columns { get; private set; }
/// <summary>
/// For internal use only.
/// Set the new columns on the mechanism.
/// </summary>
/// <param name="columns">The columns to be set.</param>
public void SetColumns(IEnumerable<Column> columns) { Columns = new ColumnCollection(columns); }
}
}
36 changes: 15 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,36 +37,30 @@ public JsonResult MyActionResult([ModelBinder(typeof(DataTablesBinder)] IDataTab
return Json(new DataTablesResponse(requestModel.Draw, paged, myFilteredData.Count(), myOriginalDataSet.Count()));
}
```
<h3>Any gotchas?</h3>
<h3>What about ordering?</h3>
<p>
There is one. Simple but tricky.
It's a no brainer too.
</p>
<p>
When sorting on client-side, DataTables send a request to your server to order by the selected columns. It defaults to the first column but you can change that.<br />
Filter/sort info from each column is, well, included on each column.
</p>
<p>
The problem comes on the server-side when dealing with IQueryable, IEnumerable and IList elements.
DataTables provides you with the sorting column indexes and directions but we don't have a method to order an IQueryable, IEnumerable or IList using the index of the field.
To help you out, get only the columns which were ordered on client-side with <code>IDataTablesRequest.GetSortedColumns()</code>.
Than, iterate through then and use <code>Column.SortDirection</code> to sort your dataset.
</p>
<p>
Also, consider that you have an unbound column (model: null). You won't find a way to order that column on server-side (but you might want to order through other columns).
</p>
<p>
So, you'll have work with 3 elements: <code>Column.IsOrdered</code>, <code>Column.OrderNumber</code> and <code>Column.SortDirection</code>.
</p>
<p>
Tips:
Sample:
</p>
```C#
var columns = requestParameters.Columns.Where(_column => _column.IsOrdered && !String.IsNullOrWhiteSpace(_column.Data));
if (columns.Any())
var filteredColumns = requestParameters.Columns.GetFilteredColumns();
foreach(var column in filteredColumns)
Filter(column.Data, column.Search.Value, column.Search.IsRegexValue);

var sortedColumns = requestParameters.Columns.GetSortedColumns();
var isSorted = false;
foreach(var column in sortedColumns)
{
var sortedColumns = columns.OrderBy(_column => _column.OrderNumber);
var isSorted = false;
foreach(var column in sortedColumns)
{
if (!isSorted) { Sort(column.Data, column.SortDirection); isSorted = true; }
else { SortAgain(column.Data, column.SortDirection); }
}
if (!isSorted) { Sort(column.Data, column.SortDirection); isSorted = true; }
else { SortAgain(column.Data, column.SortDirection); }
}
```

0 comments on commit 2848fa2

Please sign in to comment.