I want to override the default sorting mechanism of ag-grid for a specific column only. I.e. I've been able to override at the grid level, i.e.
defaultColDef: {
comparator: (a, b) => typeof a === 'string' ? a.localeCompare(b) : (a > b ? 1 : (a < b ? -1 : 0));
}
However, this does at the entire grid level - which I don't want. Is that possible?
Thanks!
I found the answer: colDef has a comparator property as well, so this actually works!
{
headerName: 'Currency',
field: 'currency',
comparator: (a, b) => typeof a === 'string' ? a.localeCompare(b) : (a > b ? 1 : (a < b ? -1 : 0));
}
This Issue can be resolved by using accentedSort to True from ag-grid ver 17.1.1
GridOptions.accentedSort = true;
Related
I've inherited some code, and also a bug.
The app is a C# MVC website using EF. The VIEW presents clients in a table (taken straight from a CLIENTS table in a SQL Server database).
List<Client> _clients = db.Client.ToList();
IEnumerable<Client> filteredClients;
The problem arises when the user clicks a header to sort by. The args passed to the controller indicate an index of the field to sort by (sortColumnIndex).
The original dev created a func to handle the translation from the index to the field.
Func<Client, string> orderingFunction = (c => sortColumnIndex == 1 ? c.Name.ToString()
: sortColumnIndex == 2 ? c.AccountExec.ToString()
: sortColumnIndex == 3 ? c.SalesforceLink.ToString()
: sortColumnIndex == 4 ? c.Location.ToString()
: sortColumnIndex == 5 ? c.PrimaryContact.ToString()
: sortColumnIndex == 6 ? c.AccountId.ToString()
: sortColumnIndex == 6 ? c.MongoClientId.ToString()
: ""); // index 0 is the hidden ClientId
The results of this are used in the OrderBy() clause.
filteredClients = filteredClients.OrderBy(orderingFunction);
When the field being sorted on has complete data (i.e. no NULL values), it works fine. As soon as a column has a NULL value, however, the resulting OrderBy throws a "Object reference not set to an instance of an object" error.
I'm afraid I'm not completely up to the task of deciphering the solution here; we still need to sort on the field selected by the user, even if all but one of the records have a NULL value. Is there any way to achieve this with the existing code structure, or is this better served by refactoring?
EDIT: full code up to the point of exception:
"param" is the argument that contains all of the filters and such.
List<Client> _clients = db.Client.ToList();
IEnumerable<Client> filteredClients;
//Check for filters. This is a search, and we can say it's empty for this purpose
if (!string.IsNullOrEmpty(param.sSearch))
{
var nameFilter = Convert.ToString(Request["bSearch_1"]); // Search string
var isNameSearchable = Convert.ToBoolean(Request["bSearchable_1"]); // Is column searchable? Optional
filteredClients = _clients.Where(x => x.Name.ToLower().Contains(param.sSearch.ToLower()));
}
else
{
filteredClients = _clients.OrderBy(x => x.Name);
}
// Sort Column
var isNameSortable = Convert.ToBoolean(Request["bSortable_1"]);
var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
Func<Client, string> orderingFunction = (c => sortColumnIndex == 1 ? c.Name.ToString()
: sortColumnIndex == 2 ? c.AccountExec.ToString()
: sortColumnIndex == 3 ? c.SalesforceLink.ToString()
: sortColumnIndex == 4 ? c.Location.ToString()
: sortColumnIndex == 5 ? c.PrimaryContact.ToString()
: sortColumnIndex == 6 ? c.AccountId.ToString()
: ""); // index 0 is the hidden ClientId
// Sort Direction
var sortDirection = Request["sSortDir_0"]; // asc or desc
if (sortDirection == "asc")
{
//Results of this line generate exception
filteredClients = filteredClients.OrderBy(orderingFunction);
}
else
{
filteredClients = filteredClients.OrderByDescending(orderingFunction);
}
Well! Thanks to johnny 5's wondering why the c.AccountId.ToString() was in use, I pulled the .ToString() from the func<>, and that seemed to do the trick.
Thanks, johnny 5! Sometimes you just need another set of eyes!
TAB_XXX and TAB_XXX_details are one-to-many relationships, I need to query the two tables, however, we need to be filtered TAB_XXX_details。
The code is as follows:
var qu = from c in db.TAB_XXX.Where(n => n.DELETE_MARK == false)
let dets = c.TAB_XXX_DETAILS.Where(n => condition.SaleType.HasValue ? n.SALE_TYPE == (decimal)condition.SaleType : 1 == 1)
select new
{
c,
dets
};
Condition.SaleType is number?, if the condition.SaleType is a valid number, such as 1, 2, 3 ... I want to filter the child record based on these numbers; when the condition.SaleType is null, I want to query TAB_XXX and all its child records;
How do I modify the where clause?
Thank you for your answer!
Since 1 == 1 is always true, your condition boils down to this:
let dets = c.TAB_XXX_DETAILS
.Where(n => !condition.SaleType.HasValue || n.SALE_TYPE == condition.SaleType.Value)
Essentially, you want to return all rows when condition.SaleType does not have value; otherwise, you make a comparison to condition.SaleType.Value.
For columns in y-dimension how to do natural sort for alpha numeric column names ?
For example:
consider column names AA1, AA2, AA3, AA10, AA11.
These are listed in order AA1, AA10, AA11, AA2, AA3 in pivot table y-dimension.
Desired order of columns is AA1, AA2, AA3, AA10, AA11
Free jqGrid 4.9 contains full rewritten version of jqPivot. I tried to hold compatibility with the previous version, but it contains many advanced features. I tried to describe there in wiki.
Not so many people uses jqPivot. So I remind what it do. It gets an input data as source and generate new data, which will be input data for jqGrid. Additionally jqPivot generates colModel based on input data and yDimension parameter. During analyzing of input data jqPivot sorts input data by xDimension and by yDimension. The order or sorting of xDimension defines the order of rows of resulting grid. The order or sorting of yDimension defines the order of columns of resulting grid and the total number of resulting columns. The options compareVectorsByX and compareVectorsByY of allows to specify callback function which will be used for custom sorting by the whole x or y vector. It's important to understand that sorting function not only specify the the order of columns, but it informs jqPivot which vectors should be interpreted as the same. For example it can interpret the values 12, 12.0 and 012.00 as the same and specify that 12.0 is larger as 6.
I describe below some ways which can be used to customize sorting by xDimension and yDimension.
First of all one can specify skipSortByX: true or skipSortByY: true parameters. In the case the input data have to be already sorted in the order which you want. The next important options are Boolean options caseSensitive (with default value false) and trimByCollect (default value true). caseSensitive: true can be used to distinguish input data by case and trimByCollect: false can be used to hold trailing spaces in the input data.
Some other important option can be specified in xDimension or yDimension: sorttype and sortorder. sortorder: "desc" can be used to reverse the order of sorted data. The option sorttype can be "integer" (or "int") which means to truncate (Math.floor(Number(inputValue))) input data during sorting; The values "number", "currency" and "float" means that the input data should be converted to numbers during sorting (Number(inputValue)). Finally one can don't specify any sorttype, but specify compare callback function instead. The compare callback is function with two parameters and it should return well known -1, 0 or 1 values.
For example I created the demo for one issue. One asked my about the following situation. The web site contains login, which identifies the country of the user. One want to set the user's country as the first in the sorting order. The demo uses the following yDimension parameter:
yDimension: [
{ dataName: "sellyear", sorttype: "integer" },
{ dataName: "sell month",
compare: function (a, b) {
if (a === "Germany") { return b !== "Germany" ? -1 : 0; }
if (b === "Germany") { return 1; }
if (a > b) { return 1; }
if (a < b) { return -1; }
return 0;
}}
]
It sets "Germany" first in the sorting order. As the results one sees the results like on the picture below
You can use the same approach using the code for natural compare from the answer and you will implements your requirements.
In more advanced cases one can use the options compareVectorsByX and compareVectorsByY. The requirement was to place specific country only in one specific year on the first place holding the standard order on all other cases. The corresponding demo uses compareVectorsByY to implement the requirement. It displays
and uses the following compareVectorsByY:
compareVectorsByY: function (vector1, vector2) {
var fieldLength = this.fieldLength, iField, compareResult;
if (fieldLength === 2) {
if (vector1[0] === "2011" && vector1[1] === "Germany") {
if (vector2[0] === "2011" && vector2[1] === "Germany") {
return {
index: -1,
result: 0
};
}
return {
index: vector2[0] === "2011" ? 1 : 0,
result: -1
};
}
// any vector1 is larger as vector2 ("2011", "Germany")
if (vector2[0] === "2011" && vector2[1] === "Germany") {
return {
index: vector2[0] === "2011" ? 1 : 0,
result: 1
};
}
}
for (iField = 0; iField < fieldLength; iField++) {
compareResult = this.fieldCompare[iField](vector1[iField], vector2[iField]);
if (compareResult !== 0) {
return {
index: iField,
result: compareResult
};
}
}
return {
index: -1,
result: 0
};
}
It's important to mention that compareVectorsByY callback function should return object with two properties: index and result. The value of result property should be -1, 0 or 1. The value of index property should be -1 in case of result: 0 and be 0-based index of vectors where vector1 and vector2 are different.
I have a given list of data :
def given = [
[Country:'Japan',Flag:'Yes',Event:'New Year'],
[Country:'china',Flag:'No',Event:'Spring Festival'],
[Country:'uk',Flag:'No',Event:'National Holiday'],
[Country:'us',Flag:'Yes',Event:'Labour Day'],
[Country:'us',Flag:'Yes',Event:'New Year'],
[Country:'uk',Flag:'Yes',Event:'Memorial Day']
]
I can sort using groovy sort method :
given = given.collect().sort { a, b ->
a.Flag <=> b.Flag ?: a.Event <=> b.Event
}
but, how would i do it if the sort by is mentioned by user and stored in separate list like
eg : def sortOrder = ["Country","Flag"], Here sort Order is dynamic that is users choice : ["Country","Flag"] / ["Country","Flag","Event"] or none. How can i write sort method so that it takes my dynamic arguments in closure ?
Assuming you have your custom order in a variable order, try
given.sort { a, b ->
order.inject(0) { o, e ->
o ?: a[e] <=> b[e]
}
}
One way would be to iterate the sortorder and use findResult to get the "ufo" results. The ugly part about this, is that findResults does not use groovy truth and sort needs an int, so some elvis action is needed to. e.g.
def given = [[Country:'Japan',Flag:'Yes',Event:'New Year'],
[Country:'china',Flag:'No',Event:'Spring Festival'],
[Country:'uk',Flag:'No',Event:'National Holiday'],
[Country:'us',Flag:'Yes',Event:'Labour Day'],
[Country:'us',Flag:'Yes',Event:'New Year'],
[Country:'uk',Flag:'Yes',Event:'Memorial Day']]
def sortorder = ['Flag', 'Event']
assert given.sort{ a,b ->
sortorder.findResult{ a[it] <=> b[it] ?: null } ?: 0
}.first()==[Country:'uk', Flag:'No', Event:'National Holiday']
I am writing a linq having a left outer join with conditions on right side table.
my code
var leftHotelRooms = db.HotelRooms.Include(hr=>hr.HotelRoomBlackoutPeriods)
.Where(room => hotelCodes.Contains(room.UserHotelId) &&
room.Scope == scope &&
room.IsDeleted == false &&
room.IsEnabled == true &&
room.MaxCapacity >= minimumNumberOfGuests)
.GroupJoin(db.HotelRoomBlackoutPeriods,
room => room.Id,
blackoutPeriod => blackoutPeriod.HotelRoomId,
(room, blackoutPeriod) => new
{
room,
blackoutPeriods = blackoutPeriod.DefaultIfEmpty()
})
.Select(a => new {a.room,a.blackoutPeriods})
.Where(
x => x.blackoutPeriods.Any(y => DbFunctions.DiffDays(y.StartDate, checkIn) != 0
&& (DbFunctions.DiffDays(y.StartDate, checkIn) < 0) ? (DbFunctions.DiffDays(y.StartDate, checkOut) >= 0 ? false : true) : true &&
(DbFunctions.DiffDays(y.StartDate, checkIn) > 0) ? (DbFunctions.DiffDays(y.EndDate, checkIn) <= 0 ? false : true) : true
))
.ToList();
}
which works perfectly fine but it does not eagerly load, when i convert result of above query to my business model it again fires some queries on db.HotelRoomBlackoutPeriods
Please provide the optimum way to achieve this.
thanks in advance.
sorry (if i am asking something nonsense ) in advance
Eager loading does not work when you change the shape of the result set. Shape of your result set is HotelRoom type. Once you use any manual join or projection, you are changing the result set and eager loading request is ignored.