Sorting order of Groups in kendo ui grid - javascript

Here I have written stored procedure for getting CategoryName values based on id, Values are coming like India, America, Brazil up to service, But in UI section values are in automatically sorting in alphabetical order displaying groups like America, Brazil,India. I wanted to show as in order display like India, America, Brazil format. What am I doing wrong? Thanks in advance.
$(document).ready(function () {
var grid = $("#grid").kendoGrid({
dataSource: {
type: "GET",
transport: {
read: {
url: "some url placed here",
dataType: "jsonp"
}
},
pageSize: 20,
serverSorting: false,
group: {
field: "CategoryName",
aggregates: [{
field: "abc",
aggregate: "count"
}, {
field: "def",
aggregate: "sum"
}, {
field: "ghi",
aggregate: "sum"
}]
},
aggregate: [{
field: "abc",
aggregate: "count"
}, {
field: "def",
aggregate: "sum"
}, {
field: "ghi",
aggregate: "sum"
}]
},
columns: [
//column section goes here.....
],
sortable: false
//...
});
});

I remember somewhere in the kendo ui documentation (may be datasource > groups) it said that, if you define groups, the grouping requires the sorted data.. Remove all your groups and display the data in plain vanilla grid and see if some automatic sorting is applied.

This is a complete guess, but have you tried setting the ServerSorting property to true?

Kendo UI Grid Grouping gives you ListSortDirection.Ascending sorting by default. If you want to do something else you have to set it. If you are using the WebApi interface and generating a kendoRequest for the Kendo.mvc.dll method .ToDataSourceResult(kendoRequest); then you may try something like this:
var sort = kendoRequest.Sorts.FirstOrDefault();
var group = kendoRequest.Groups.FirstOrDefault();
if(sort != null && group != null) {
if(sort.Member == group.Member && sort.SortDirection == ListSortDirection.Descending) {
kendoRequest.Groups[0].SortDirection = sort.SortDirection;
}
}
That way the Sort feature from the Grid affects the Group by column when they match.

Related

Server side pagination in KTDatatable (Metronic)

I am new to KTDatatable in Metronic.
I am trying to use server side pagination in Metronic dashboard, and I am parsing the data in a KTDatatable, but I can't find a way to parse the returned data from the API and to view number of pages and each page URL.
The code that I was able to write so far is:
data: {
type: 'remote',
source: {
read: {
url: dataURL,
method: 'GET',
contentType: 'application/json',
map: function(data) {
var cards = data.cards.data;
var currentPage = data.cards.current_page;
var lastPage = data.cards.last_page;
return cards;
}
},
},
pageSize: 10,
serverPaging: true,
},
In this code I was able to get the first ten records but:
1- I wasn't able to parse them the way I want in the table.
2- I wasn't able to show the pages number nor calling the API for the second page or the (x) page I want.
These are the things I want to do.
Thanks in advance.
You can go back to the end of the KT-Datatable documentation to find most of answers you want KT-Datable documentation, but I am gonna explain more hoping it will be more clear.
So the returned value from the API (Json) should look have two main objects meta and data, and it looks something like this:
{
"meta": {
"sort": "desc",
"field": "IssueName",
"page": 1,
"pages": 2,
"perpage": "10",
"total": 11
},
"data": [
{
"IssueName": "******",
"CardNumber": "******"
},
{
"IssueName": "******",
"CardNumber": "******"
}
]
}
And after getting the values of the response from the API you should only return the data object to be parsed by the datatable so the map function should look something like this:
map: function(data) {
return data.data;
}
and it will process the meta data itself.
To parse the data into the columns you should use the same key name of the data in column definition array, so in my example I used it like this:
columns: [
{
field: 'IssueName',
title: columnsTitles.issue,
type: 'string',
},
{
field: 'CardNumber',
title: columnsTitles.card_number,
type: 'string',
},
]
And every time the datatable calls the API it will send more data that will help you give the right response, the data will be on a shape of an array (The field name should be the same as the key):
[
"pagination" => array:4 [
"page" => "1"
"pages" => "2"
"perpage" => "10"
"total" => "11"
],
"sort" => array:2 [
"field" => "IssueName"
"sort" => "desc"
],
]
The sent data is related with the pagination and sorting type you have to get from the API, and you can also add filters and they will be stored in the array in the "query" field, and you can handle them in the backend.

nested autocomplete with selectize plugin

I am using the query-builder plugin in combination with selectize.js plugin to have autocomplete in my query-builder enabled and it works perfectly.
What I would like to know is whether there is any out of the box way to achieve nested autocomplete with selectize.js, or if not any, which part of code could I customize in the plugin to achieve this functionality.
Example of current autocomplete
Code of current autocomplete
values = [{...}] //values holds the json array of the example
plugin = 'selectize';
input = 'text';
plugin_config = {
valueField: 'value',
labelField: 'value',
searchField: ['value'],
sortField: 'value',
nesting: true,
searchFieldOptions: [{nesting: true}],
create: true,
maxItems: 1,
onInitialize: function() {
var that = this;
values.forEach(function(item) {
that.addOption(item);
});
}
};
valueSetter = function(rule, value) {
rule.$el.find('.rule-value-container input')[0].selectize.setValue(value);
}
JSON example
[{
"value": "AnyRole",
"arrayofobjs": [{
"value": "firstobj"
},
{
"value": "secondobj"
}
]
},
{
"value": "Administrator",
"arrayofobjs": [{
"value": "firstobj"
},
{
"value": "secondobj"
}
]
}]
Considering the json sample above, I would like to search inside arrayofobjs when typing the . notation after an option of object values as shown below.
a
AnyRole
Administrator
Manager
and when selecting f.e 'Administrator' and type the dot notation
Administrator.
firstobj
secondobj
The same way editors do with objects.
Is there anything out of the box? I have searched in the selectize.js examples as well as into other threads on GitHub but did not find anything related to it. In case there is not any, I could make a custom solution myself but it would be great if anyone gives me any tips on which part of code and what should I do, thanks in advance :)

Unflattening line items in inputData when rendered by function

I have dynamic children input fields that need to be rendered in a function, but when they are, then they are not included in inputData properly/not under the parent input field's key. When the children are included directly in the inputFields, it works as expected, but I can't use a function within the children array with Zapier.
Here is the inputData currently, when the line items are rendered in a function, the LI_ denotes that it is a child input key -
"inputData": {
"supplier": "1",
"LI_budget": 1,
"LI_tax": 1,
"company": "1",
"currency": "1",
"LI_price": "1",
"LI_description": "1"
}
I'm expecting ("parent" is the inputField parent key here):
"inputData": {
"supplier": "1",
"parent": [{
"LI_budget": 1,
"LI_tax": 1,
"LI_price": "1",
"LI_description": "1"
}],
"company": "1",
"currency": "1",
}
This is the function I'm using to pull in the parent and children input fields:
const getLineItems = async (z, bundle) => {
let lineItem = {
key: 'parent',
children: [{
key: 'LI_description',
label: 'Description',
required: true
},
{
key: 'LI_budget',
required: true,
label: 'Budget',
dynamic: 'budget.id'
},
{
key: 'LI_price',
required: true,
type: 'number',
label: 'Unit price',
helpText: 'Example: 50.25'
},
{
key: 'LI_tax',
required: true,
label: 'Tax Rate',
dynamic: 'tax_rate.id'
},
]
}
return [lineItem];
};
There are dynamic fields generated in the getLineItems function that I took out to simplify. TIA
Caleb here from Zapier Platform Support. This is a tough one! We have a pretty long-standing issue report on our platform for supporting custom fields with parent keys (it boils down to a chicken vs the egg problem that really makes my head spin when I read the discussion on the issue). Your inputFields function is spot-on, it's just a matter of properly storing it in the bundle on our part.
I think we could cobble together a workaround to unflatten it. Before I do that though, could you give this a test in the editor and submit actual line items from a previous step to this step? I'm not sure what the inputData looks like (e.g. if multiple items are split like 1,2,3 or in some other fashion). If you want to iterate on this, it might be better to switch over to our public developer Slack (http://zpr.io/ttvdr); then we can post the results here for the next person to run into this. 😁

Add fields in DevExpress Pivot using AngularJS

I'm looking at this template to build a web application: https://js.devexpress.com/Demos/WidgetsGallery/Demo/PivotGrid/FieldChooser/AngularJS/Light/
In the example there are static data. I have to retrieve them from the server. So, I wrote this:
$scope.testData = [];
$scope.pivotGridDataSource = new DevExpress.data.PivotGridDataSource({
fields: [{
caption: "Nome",
dataField: "fullName",
area: "row"
}, {
caption: "Country",
dataField: "country",
area: "column"
}, {
caption: "Count",
dataField: "countOne",
dataType: "number",
summaryType: "sum",
area: "data"
}],
store: $scope.testData
});
$scope.pivotGridOptions = {
allowSortingBySummary: true,
allowSorting: true,
allowFiltering: true,
showBorders: true,
dataSource: $scope.pivotGridDataSource,
fieldChooser: {
enabled: false
}
},
$scope.fieldChooserOptions = {
dataSource: $scope.pivotGridDataSource,
texts: {
allFields: "All",
columnFields: "Columns",
dataFields: "Data",
rowFields: "Rows",
filterFields: "Filter"
},
width: 400,
height: 400,
bindingOptions: {
layout: "layout"
}
};
// Now I call the server to retrieve data
$scope.getTestData = () => {
$scope.testData.length = 0;
result.forEach(e => {
$scope.testData.push(e);
);
$scope.pivotGridDataSource.reload();
}
$scope.getTestData();
The problem is that when the data are loaded, in the Fields below it shows just the fields written at the beginning (so the name, the count and the country). But I saw in the demo that it should be display ALL parameters of the object.
For example, if the object is so structured:
{ "name": "Test1", "country": "Germany", "creationDate": "xxx", "surname": "yyy" }
So, I expect that in the fields there should be ALL parameters, so name, country, creationDate, surname. So, I did this at the beginning:
I changed $scope.testData = [] into:
$scope.testData = [{ "name": "", "country": "", "creationDate": "", "surname": "" }]
so the component will preparare all fields. And this works. But what if the server gives me back an Object that has another parameters? How can I display them?
I tried so after the calling and before the reload():
let fields = $scope.pivotGridDataSource.fields();
let newField = {
llowExpandAll: false,
allowFiltering: true,
allowSorting: true,
allowSortingBySummary: true,
caption: "This is a new field",
dataField: "newField",
dataType: "string",
displayFolder: "",
index: fields.length
}
$scope.pivotGridDataSource.fields().push(newField);
$scope.pivotGridDataSource.reload();
But it doesn't work yet. Worse, it does not even initialize the Pivot.
The fieldChooser uses the store fields, in this case $scope.testData fields, in your code I see your store is first declared (as null or with some format as you described) and then you have a function to fill it.
I don't know how your code looks and why you create your store that way, but that is basically your problem (the flow).
In the sample code the flow is:
Store with data (static in this case)
PivotGridDataSource
FieldChooser
In your code the flow is:
Store (empty)
PivotGridDataSource
FieldChooser
Store (fill) --> at this point your FieldChooser has been initialized with the fields of the empty version of your store so not much to do (in Jquery you could re-create your object, you dan do it using Jquery within AngularJs see a simple code sample here and below)
$('#chartContainer').dxChart('instance').dispose();
$('#chartContainer').dxPieChart({
...
});
To avoid all of this you can just use the DevExpress.data.CustomStore and your flow will be basically identical to the demo.

Kendo grid: How to remote filter above 2 values from one column

I have one column in kendo grid but if i'm filtering opposite the server API i need to filter against two values.
It means something like this:
{
"entityName": "client",
"data": {
"take": 10,
"skip": 0,
"page": 1,
"pageSize": 10,
"filter": {
"logic": "and",
// IN FILTER IS IMPORTANT TO HAVE 2 OBJECTS
"filters": [
{
"operator": "eq",
"value": "test",
"field": "client.name"
},
{
"operator": "eq",
"value": "test",
"field": "client.surname"
}
]
},
"group": []
}
}
I tried it by this way:
filterable : {
cell :
[
{
dataTextField : "client.name",
operator : "contains"
},
{
dataTextField : "client.surname",
operator : "contains"
}
]
}
But without luck.
How can i do it please?
Many thanks for any advice.
In order to do this, you'll have to intercept the dataSource data request and change the filter inside the readOptions before it get to the server. You'll have to create a custom transport.read and each time the dataSource will request some data, it will pass the readOptions parameter to that function.
myGrid.kendoGrid({
dataSource: {
serverFiltering: true,
transport: {
read: function (readOptions) {
readOptions.filter.filters = [{
operator: "eq",
value: "test",
field: "client.name"
}, {
operator: "eq",
value: "test",
field: "client.surname"
}];
//Insert you logic to retrieve the data from the server
//You may also try to call the dataSource original read function and pass the modified readOptions
//The ajax is just an example...
$.ajax({data: readOptions}).done(function(data){
readOptions.success(data);
});
}
}
}
Remember that if you overwrite the read function, you are responsible to call the readOptions success / error function to notify the dataSource about the data callback.

Categories

Resources