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

Commit 2848fa2

Browse files
committed
Helper methods on column collection.
Added helper methods and a ColumnCollection object to help you when getting both filtered and sorted columns. Improved sample code.
1 parent 0f65621 commit 2848fa2

File tree

5 files changed

+140
-40
lines changed

5 files changed

+140
-40
lines changed

DataTables.Mvc/ColumnCollection.cs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#region Copyright
2+
/* The MIT License (MIT)
3+
4+
Copyright (c) 2014 Anderson Luiz Mendes Matos
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
THE SOFTWARE.
23+
*/
24+
#endregion Copyright
25+
using System;
26+
using System.Collections.Generic;
27+
using System.Linq;
28+
using System.Text;
29+
using System.Threading.Tasks;
30+
31+
namespace DataTables.Mvc
32+
{
33+
/// <summary>
34+
/// Represents a read-only DataTables column collection.
35+
/// </summary>
36+
public class ColumnCollection : IEnumerable<Column>
37+
{
38+
/// <summary>
39+
/// For internal use only.
40+
/// Stores data.
41+
/// </summary>
42+
private IReadOnlyList<Column> Data;
43+
/// <summary>
44+
/// Created a new ReadOnlyColumnCollection with predefined data.
45+
/// </summary>
46+
/// <param name="columns">The column collection from DataTables.</param>
47+
public ColumnCollection(IEnumerable<Column> columns)
48+
{
49+
if (columns == null) throw new ArgumentNullException("The provided column collection cannot be null", "columns");
50+
Data = columns.ToList().AsReadOnly();
51+
}
52+
/// <summary>
53+
/// Get sorted columns on client-side already on the same order as the client requested.
54+
/// The method checks if the column is bound and if it's ordered on client-side.
55+
/// </summary>
56+
/// <returns>The ordered enumeration of sorted columns.</returns>
57+
public IOrderedEnumerable<Column> GetSortedColumns()
58+
{
59+
return Data
60+
.Where(_column => !String.IsNullOrWhiteSpace(_column.Data) && _column.IsOrdered)
61+
.OrderBy(_c => _c.OrderNumber);
62+
}
63+
/// <summary>
64+
/// Get filtered columns on client-side.
65+
/// The method checks if the column is bound and if the search has a value.
66+
/// </summary>
67+
/// <returns>The enumeration of filtered columns.</returns>
68+
public IEnumerable<Column> GetFilteredColumns()
69+
{
70+
return Data
71+
.Where(_column => !String.IsNullOrWhiteSpace(_column.Data) && _column.Searchable && !String.IsNullOrWhiteSpace(_column.Search.Value));
72+
}
73+
/// <summary>
74+
/// Returns the enumerable element as defined on IEnumerable.
75+
/// </summary>
76+
/// <returns>The enumerable elemento to iterate through data.</returns>
77+
public IEnumerator<Column> GetEnumerator()
78+
{
79+
return Data.GetEnumerator();
80+
}
81+
/// <summary>
82+
/// Returns the enumerable element as defined on IEnumerable.
83+
/// </summary>
84+
/// <returns>The enumerable element to iterate through data.</returns>
85+
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
86+
{
87+
return ((System.Collections.IEnumerable)Data).GetEnumerator();
88+
}
89+
}
90+
}

DataTables.Mvc/DataTables.Mvc.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
<Compile Include="IDataTablesRequest.cs" />
8383
<Compile Include="NameValueCollectionExtensions.cs" />
8484
<Compile Include="Properties\AssemblyInfo.cs" />
85+
<Compile Include="ColumnCollection.cs" />
8586
<Compile Include="Search.cs" />
8687
</ItemGroup>
8788
<ItemGroup>

DataTables.Mvc/DataTablesBinder.cs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,10 @@ public object BindModel(ControllerContext controllerContext, ModelBindingContext
106106
ParseColumnOrdering(requestParameters, columns);
107107

108108
// Attach columns into the model.
109-
model.AddColumns(columns);
109+
model.SetColumns(columns);
110110

111111
// Returns the filled model.
112-
return model;
112+
return (IDataTablesRequest)model;
113113
}
114114
/// <summary>
115115
/// Resolves the NameValueCollection from the request.
@@ -148,7 +148,7 @@ protected virtual List<Column> GetColumns(NameValueCollection collection)
148148
{
149149
try
150150
{
151-
var returnCollection = new List<Column>();
151+
var columns = new List<Column>();
152152

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

166-
var column = new Column(
167-
columnData,
168-
columnName,
169-
columnSearchable,
170-
columnOrderable,
171-
columnSearchValue,
172-
columnSearchRegex);
173-
174-
returnCollection.Add(column);
166+
columns.Add(new Column(columnData, columnName, columnSearchable, columnOrderable, columnSearchValue, columnSearchRegex));
175167
}
176168
else break; // Stops iterating because there's no more columns.
177169
}
178170

179-
return returnCollection;
171+
return columns;
180172
}
181173
catch
182174
{
175+
// Returns an empty column collection to avoid null exceptions.
183176
return new List<Column>();
184177
}
185178
}

DataTables.Mvc/IDataTablesRequest.cs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,22 +57,44 @@ public interface IDataTablesRequest
5757
/// <summary>
5858
/// Gets the read-only collection of client-side columns with their options and configs.
5959
/// </summary>
60-
IReadOnlyCollection<Column> Columns { get; }
60+
ColumnCollection Columns { get; }
6161
}
6262
/// <summary>
6363
/// For internal use only.
6464
/// Represents DataTables request parameters.
6565
/// </summary>
6666
class DataTablesRequest : IDataTablesRequest
6767
{
68+
/// <summary>
69+
/// For internal use only.
70+
/// Gets/Sets the draw counter from DataTables.
71+
/// </summary>
6872
public int Draw { get; set; }
73+
/// <summary>
74+
/// For internal use only.
75+
/// Gets/Sets the start record number (jump) for paging.
76+
/// </summary>
6977
public int Start { get; set; }
78+
/// <summary>
79+
/// For internal use only.
80+
/// Gets/Sets the length of the page (paging).
81+
/// </summary>
7082
public int Length { get; set; }
83+
/// <summary>
84+
/// For internal use only.
85+
/// Gets/Sets the global search term.
86+
/// </summary>
7187
public Search Search { get; set; }
72-
private List<Column> _Columns { get; set; }
73-
public IReadOnlyCollection<Column> Columns { get { return _Columns.AsReadOnly(); } }
74-
public DataTablesRequest() { _Columns = new List<Column>(); }
75-
public void AddColumn(Column column) { _Columns.Add(column); }
76-
public void AddColumns(IEnumerable<Column> columns) { _Columns.AddRange(columns); }
88+
/// <summary>
89+
/// For internal use only.
90+
/// Gets/Sets the column collection.
91+
/// </summary>
92+
public ColumnCollection Columns { get; private set; }
93+
/// <summary>
94+
/// For internal use only.
95+
/// Set the new columns on the mechanism.
96+
/// </summary>
97+
/// <param name="columns">The columns to be set.</param>
98+
public void SetColumns(IEnumerable<Column> columns) { Columns = new ColumnCollection(columns); }
7799
}
78100
}

README.md

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,36 +37,30 @@ public JsonResult MyActionResult([ModelBinder(typeof(DataTablesBinder)] IDataTab
3737
return Json(new DataTablesResponse(requestModel.Draw, paged, myFilteredData.Count(), myOriginalDataSet.Count()));
3838
}
3939
```
40-
<h3>Any gotchas?</h3>
40+
<h3>What about ordering?</h3>
4141
<p>
42-
There is one. Simple but tricky.
42+
It's a no brainer too.
4343
</p>
4444
<p>
45-
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 />
45+
Filter/sort info from each column is, well, included on each column.
4646
</p>
4747
<p>
48-
The problem comes on the server-side when dealing with IQueryable, IEnumerable and IList elements.
49-
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.
48+
To help you out, get only the columns which were ordered on client-side with <code>IDataTablesRequest.GetSortedColumns()</code>.
49+
Than, iterate through then and use <code>Column.SortDirection</code> to sort your dataset.
5050
</p>
5151
<p>
52-
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).
53-
</p>
54-
<p>
55-
So, you'll have work with 3 elements: <code>Column.IsOrdered</code>, <code>Column.OrderNumber</code> and <code>Column.SortDirection</code>.
56-
</p>
57-
<p>
58-
Tips:
52+
Sample:
5953
</p>
6054
```C#
61-
var columns = requestParameters.Columns.Where(_column => _column.IsOrdered && !String.IsNullOrWhiteSpace(_column.Data));
62-
if (columns.Any())
55+
var filteredColumns = requestParameters.Columns.GetFilteredColumns();
56+
foreach(var column in filteredColumns)
57+
Filter(column.Data, column.Search.Value, column.Search.IsRegexValue);
58+
59+
var sortedColumns = requestParameters.Columns.GetSortedColumns();
60+
var isSorted = false;
61+
foreach(var column in sortedColumns)
6362
{
64-
var sortedColumns = columns.OrderBy(_column => _column.OrderNumber);
65-
var isSorted = false;
66-
foreach(var column in sortedColumns)
67-
{
68-
if (!isSorted) { Sort(column.Data, column.SortDirection); isSorted = true; }
69-
else { SortAgain(column.Data, column.SortDirection); }
70-
}
63+
if (!isSorted) { Sort(column.Data, column.SortDirection); isSorted = true; }
64+
else { SortAgain(column.Data, column.SortDirection); }
7165
}
7266
```

0 commit comments

Comments
 (0)