I am using AlloyUI to display a table with pagination + datatable-sort.
Problem: The data is sorted ONLY on the current page.
Instead I want to sort all the data each time I click on a column and I want the user to be sent back to the first page.
How my code works: I divide my big table into small ones and link each table with a page.
Here is my code:
YUI().use('aui-datatable', 'aui-pagination', 'datatable-sort', function (Y)
{
dataPages = [{ .... }, { ... }, ... , { ... }]; => contains 18 rows
var columns = [
{ key: 'Tel', label: 'Tel', sortable: true },
...
{ key: 'Register', label: 'Register', sortable: true }
];
var dataTable = new Y.DataTable(
{ columns: columns, data: dataPages}
).render('#DataTableConsult');
new Y.Pagination(
{contentBox: '#pagination .aui-pagination-content', page: 1,
on: { changeRequest: function (event) {
var dataPageOne = new Array(); ... i fill in this first table with lines N° 0 to 6 of dataPages table
var dataPageTwo = new Array(); ... i fill in this first table with lines N° 7 to 13 of dataPages table
var dataPageThree = new Array(); ... i fill in this first table with lines N° 14 to 17 of dataPages table
if (event.state.page === 1) { dataTable.set('data', dataPageOne); }
else if (event.state.page === 2) { dataTable.set('data', dataPageTwo); }
else if (event.state.page === 3) { dataTable.set('data', dataPageThree); }}}}).render();
});
You can make this work with a few changes:
You need a hidden DataTable which contains all the data:
var hiddenDataTable = new Y.DataTable({
columns: columns,
data: dataPages
});
Instead of listening to the Paginator's changeRequest event, listen to the pageChange event:
on: { pageChange: function (event) { // ...
In the pageChange function, set each page to a slice of the hiddenDataTable's data.
var hiddentData = hiddenDataTable.get('data')._items;
var dataPageOne = hiddentData.slice(0, 6);
var dataPageTwo = hiddentData.slice(6, 12);
var dataPageThree = hiddentData.slice(12, 18);
Finally, listen for the sort event of the visible DataTable, and sort the hidden DataTable and set the page to 1:
dataTable.on('sort', function (event) {
hiddenDataTable.sort(event.sortBy);
pagination.set('page', 1);
});
Once you do this, all data will be sorted every time you sort by a column, and the user will be sent to the first page. Here is a runnable example using your sample code:
YUI().use('aui-datatable', 'aui-pagination', 'datatable-sort', function(Y) {
var dataPages = [{
Tel: '345678901',
Register: '\x65\x66\x67\x68\x69\x70\x71\x72'
}, {
Tel: '456789012',
Register: '\x66\x67\x68\x69\x70\x71\x72\x73'
}, {
Tel: '567890123',
Register: '\x67\x68\x69\x70\x71\x72\x73\x74'
}, {
Tel: '678901234',
Register: '\x68\x69\x70\x71\x72\x73\x74\x75'
}, {
Tel: '789012345',
Register: '\x69\x70\x71\x72\x73\x74\x75\x76'
}, {
Tel: '890123456',
Register: '\x70\x71\x72\x73\x74\x75\x76\x77'
}, {
Tel: '901234567',
Register: '\x71\x72\x73\x74\x75\x76\x77\x78'
}, {
Tel: '012345678',
Register: '\x72\x73\x74\x75\x76\x77\x78\x79'
}, {
Tel: '123456789',
Register: '\x73\x74\x75\x76\x77\x78\x79\x80'
}, {
Tel: '234567890',
Register: '\x74\x75\x76\x77\x78\x79\x80\x81'
}, {
Tel: '345678901',
Register: '\x75\x76\x77\x78\x79\x80\x81\x82'
}, {
Tel: '456789012',
Register: '\x76\x77\x78\x79\x80\x81\x82\x83'
}, {
Tel: '567890123',
Register: '\x77\x78\x79\x80\x81\x82\x83\x84'
}, {
Tel: '321014567',
Register: 'asdfasdf'
}, {
Tel: '786234567',
Register: 'zxcvsdfg'
}, {
Tel: '451234567',
Register: 'rtyucvbn'
}, {
Tel: '678901234',
Register: '\x78\x79\x80\x81\x82\x83\x84\x85'
}, {
Tel: '789012345',
Register: '\x79\x80\x81\x82\x83\x84\x85\x86'
}, {
Tel: '890123456',
Register: '\x80\x81\x82\x83\x84\x85\x86\x87'
}, {
Tel: '901234567',
Register: '\x81\x82\x83\x84\x85\x86\x87\x88'
}];
var columns = [{
key: 'Tel',
label: 'Tel',
sortable: true
}, {
key: 'Register',
label: 'Register',
sortable: true
}];
var hiddenDataTable = new Y.DataTable({
columns: columns,
data: dataPages
});
var dataTable = new Y.DataTable({
columns: columns
}).render('#DataTableConsult');
var pagination = new Y.Pagination({
contentBox: '#pagination .aui-pagination-content',
page: 1,
on: {
pageChange: function(event) {
var hiddentData = hiddenDataTable.get('data')._items;
var dataPageOne = hiddentData.slice(0, 6);
var dataPageTwo = hiddentData.slice(6, 12);
var dataPageThree = hiddentData.slice(12, 18);
if (event.newVal === 1) {
dataTable.set('data', dataPageOne);
} else if (event.newVal === 2) {
dataTable.set('data', dataPageTwo);
} else if (event.newVal === 3) {
dataTable.set('data', dataPageThree);
}
}
}
}).render();
dataTable.on('sort', function(event) {
hiddenDataTable.sort(event.sortBy);
pagination.set('page', 1);
});
});
<script src="http://cdn.alloyui.com/2.0.0/aui/aui-min.js"></script>
<link href="http://cdn.alloyui.com/2.0.0/aui-css/css/bootstrap.min.css" rel="stylesheet"></link>
<div id="pagination">
<ul class="pagination aui-pagination-content">
<li>Prev
</li>
<li>1
</li>
<li>2
</li>
<li>3
</li>
<li>Next
</li>
</ul>
</div>
<div id="DataTableConsult"></div>
Note: This method will not scale very well (because it sends all the data to the client), so I recommend doing this kind of sorting on the back end and sending only the current page to the client. Also, this does not seem very user friendly.
Related
What I'm trying to accomplish is to apply an "automatic" secondary column sort when a user sorts a column in a kendo grid.
So in this JS fiddle example, if a user sorts by "Value", it'll also sort by "Name". Note that the 0s are sorted together, but the names aren't alphabetical. I'd like them to be alphabetical (the secondary sort).
Here's an attempt at overriding the datasource sorting to accomplish this. I'm taking the user's original sort and the adding an additional sort on "SortedName". Based on the sorting array that's logged, it seems to be close but is still not working.
Any other ideas on how to accomplish this?
Note: I don't want to allow users to sort by multiple columns. The real world example I'm using this for can have up to 50+ columns (unfortunately), so multiple sort can get confusing / unintuitive. And I'd like it to be done behind the scenes without extra user interaction.
Example code for overriding kendo datasource sort():
dataSource.originalSort = dataSource.sort;
dataSource.sort = function () {
// take the user's sort and apply sorting on an additional column
// the sort array should look like this:
[
{ field: "Value", dir: "asc" }, // this is what the user sorted by
{ field: "SortedName", dir: "asc" }, // and I'm adding this
]
return dataSource.originalSort.apply(this, arguments);
}
Please try with the below code snippet.
<div id="grid">
</div>
<script>
var dataSource = new kendo.data.DataSource({
data: [
{ Name: "Lisa", Value: 1 },
{ Name: "Dan", Value: 12 },
{ Name: "Ken", Value: 5 },
{ Name: "Arthur", Value: 15 },
{ Name: "Bob", Value: 0 },
{ Name: "Sally", Value: 0 },
{ Name: "Alexis", Value: 0 },
{ Name: "Cody", Value: 0 },
{ Name: "Steve", Value: 0 },
{ Name: "Andrew", Value: 0 },
{ Name: "Duke", Value: 0 }
],
schema: {
model: {
fields: {
Name: { type: "string" },
Value: { type: "number" }
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
dataBound: function (e) {
var isSortedByName = false;
var grid = $("#grid").data("kendoGrid");
var ds = grid.dataSource;
var sort = ds.sort();
if (sort) {
for (var i = 0; i < sort.length; i++) {
if (sort[i].field == "Name") {
isSortedByName = true;
}
}
if (isSortedByName == false) {
sort.push({ field: "Name", dir: "asc" });
ds.sort(sort);
}
}
},
columns: [
{ field: "Name" },
{ field: "Value" }
],
sortable: true
});
</script>
I am trying to modify the the YUI dataTable to add rows dynamically after the dataTable is created but instead of adding one new row it adds two.
My code:
var index = 0;
YUI({
filter: 'RAW'
}).use([
'node',
'io',
'datasource',
'json-parse',
'json-stringify',
'datatable',
'datatable-sort',
'datatable-mutable',
'datatable-scroll',
'datatable-paginator',
'model-list'
],
function(Y) {
var dataTableColumns = [
{
key: 'id',
label: '#'
},
{
key: 'name',
label: 'Name',
allowHTML: true,
formatter: function (valueObject) {
return valueObject.name;
}
}
];
var dataTable = new Y.DataTable({
width: "100%",
columns: dataTableColumns,
plugins: [{
cfg: {
highlightRange: false
},
fn: Y.Plugin.DataTableHighlight
}]
}
);
dataTable.render('#dataTableDiv');
var dataSource = new Y.DataSource.IO({
source: "/localhost/data/"
});
dataSource.plug({fn: Y.Plugin.DataSourceJSONSchema, cfg: {
schema: {
resultFields: [
{key: "id"},
{key: "name"}
]
}
}});
dataTable.plug(Y.Plugin.DataTableDataSource, {
datasource: dataSource
});
dataTable.datasource.load();
Y.one("#addButton").on('click', function (event) {
index++;
var rowData = {
id: index,
name: "Test row"
};
dataTable.addRow(rowData, {index: 0});
});
}
);
So After DataTable is created I have:
And after dataTable.addRow(rowData, {index: 0}); I have:
I am using two kendo inline grid parent and child. child grid contains the list of products,when user select the products(multiple selection) from child grid and clicked to save button,it's inserted into an parent grid.
Child grid:
var selectedIds = {};
var ctlGrid = $("#KendoWebDataGrid3");
ctlGrid.kendoGrid({
dataSource: {
data:data1,
schema: {
model: {
id: 'id',
fields: {
select: {
type: "string",
editable: false
},
Qty: {
editable: true,
type: "number",
validation: { min: 1, required: true }
},
Unit: {
editable: false,
type: "string"
},
StyleNumber: {
editable: false,
type: "string"
},
Description: {
editable: false,
type: "string"
}
}
}
},
pageSize: 5
},
editable: 'inline',
selectable: "multiple",
sortable: {
mode: 'single',
allowUnsort: false
},
pageable: true,
columns: [{
field: "select",
title: " ",
template: '<input type=\'checkbox\' />',
sortable: false,
width: 35},
{
title: 'Qty',
field: "Qty",
width:90},
{
field: 'Unit',
title: 'Unit',
width: 80},
{
field: 'StyleNumber',
title: 'Style Number',
},
{
field: 'Description',
width: 230},
{command: [<!---{text:"Select" ,class : "k-button",click: selectProduct},--->"edit" ], title: "Command", width: 100 }
],
dataBound: function() {
var grid = this;
//handle checkbox change
grid.table.find("tr").find("td:first input")
.change(function(e) {
var checkbox = $(this);
var selected = grid.table.find("tr").find("td:first input:checked").closest("tr");
grid.clearSelection();
//persist selection per page
var ids = selectedIds[grid.dataSource.page()] = [];
if (selected.length) {
grid.select(selected);
selected.each(function(idx, item) {
ids.push($(item).data("id"));
});
}
})
.end()
.mousedown(function(e) {
e.stopPropagation();
})
//select persisted rows
var selected = $();
var ids = selectedIds[grid.dataSource.page()] || [];
for (var idx = 0, length = ids.length; idx < length; idx++) {
selected = selected.add(grid.table.find("tr[data-id=" + ids[idx] + "]") );
}
selected
.find("td:first input")
.attr("checked", true)
.trigger("change");
}
});
var grid = ctlGrid.data("kendoGrid");
grid.thead.find("th:first")
.append($('<input class="selectAll" type="checkbox"/>'))
.delegate(".selectAll", "click", function() {
var checkbox = $(this);
grid.table.find("tr")
.find("td:first input")
.attr("checked", checkbox.is(":checked"))
.trigger("change");
});
save button clicked Event
function selectProduct()
{
//Selecting child Grid
var gview = $("#KendoWebDataGrid3").data("kendoGrid");
//Getting selected rows
var rows = gview.select();
//Selecting parent Grid
var parentdatasource=$("#grid11").data("kendoGrid").dataSource;
var parentData=parentdatasource.data();
//Iterate through all selected rows
rows.each(function (index, row)
{
var selectedItem = gview.dataItem(row);
var selItemJson={id: ''+selectedItem.id+'', Qty:''+selectedItem.Qty+'',Unit:''+selectedItem.Unit+'',StyleNumber:''+selectedItem.StyleNumber+'',Description:''+selectedItem.Description+''};
//parentdatasource.insert(selItemJson);
var productsGrid = $('#grid11').data('kendoGrid');
var dataSource = productsGrid.dataSource;
dataSource.add(selItemJson);
dataSource.sync();
});
closeWindow();
}
Parent Grid:
var data1=[];
$("#grid11").kendoGrid({
dataSource: {
data:data1,
schema: {
model: { id: "id" ,
fields: {
Qty: { validation: { required: true } },
Unit: { validation: { required: true } },
StyleNumber: { validation: { required: true } },
Description: { validation: { required: true } }
}
}
},
pageSize: 5
},
pageable: true,
height: 260,
sortable: true,
toolbar: [{name:"create",text:"Add"}],
editable: "inline",
columns: [
{field: "Qty"},
{field: "Unit"},
{field: "StyleNumber"},
{field: "Description"},
{ command: ["edit", "destroy"], title: " ", width: "172px" }]
});
$('#grid11').data().kendoGrid.bind("change", function(e) {
$('#grid11').data().kendoGrid.refresh();
});
$('#grid11').data().kendoGrid.bind('edit',function(e){
if(e.model.isNew()){
e.container.find('.k-grid-update').click(function(){
$('#grid11').data().kendoGrid.refresh();
}),
e.container.find('.k-grid-cancel').click(function(){
$('#grid11').data().kendoGrid.refresh();
})
}
})
Adding data into parent grid work nicely,no issue,but when i select the parent grid add new row to edit then trigger the cancel button row was deleted.
I am not able to figure out the problem.please help me.
I found the error, hope can help you.
If you did not config the dataSource: schema: model's "id" field, when click edit in another row before update or click cancel, it will delete the row.
var dataSource = new kendo.data.DataSource({
...
schema: {
model: {
id:"id", // Look here, if you did not config it, issue will happen
fields: {...
...}
}
}
...
})
I have the same issue, and I config cancel like :
...
cancel: function(e) {
this.refresh();
},
...
I don't think it's the best way, but it's working.
Hope another people can give us a better way.
after saving I call $('#grid').data('kendoGrid').dataSource.read();
that cancels the edit row and reads any changes.
Still doesn't seem to be fixed.
I'm addressing it with 'preventDefault()'. This may require explicit closing of window as a consequence.
cancel: function (e) {
// Not sure why this is needed but otherwise removes row...
e.preventDefault();
e.container.data("kendoWindow").close();
},
schema: {
model: { id: "StyleNumber" // "Any ID Field from the Fields list" ,
fields: {
Qty: { validation: { required: true } },
Unit: { validation: { required: true } },
StyleNumber: { validation: { required: true } },
Description: { validation: { required: true } }
}
}
}
This will solve your problem.
I am using kendo ui v.2013.1.514, however a really terrible bug was encountered when I was using the grid widget.
As u can see, I set the virtual scroll option to 'true', and have a page size of 25. After I add a new row to the grid using addRow function, the web browser will crash every time scrolling down the grid. That was really bad, cause I need the virtualization and I need to add some new records to the grid, too. I paste some test codes below, hope this could do some help.
BTW, I test on your local demo 'virtualization-local-data.html', all the same. Seems the code just run loops in the 'range' function of DataSource widget.
<script>
$(function() {
var arrayDataSource = [];
for (var i = 0; i < 1000; i++) {
arrayDataSource.push({
check: true,
ip: "10.1.201.3"
});
}
$('#grid').kendoGrid({
height: 600,
dataSource: {
data: arrayDataSource,
schema: {
model: {
fields: {
check: { type: 'boolean' },
ip: { type: 'string' }
}
}
},
pageSize: 25
},
columns: ['check', 'ip'],
editable: false,
scrollable: {
virtual: true
}
});
$('#add').click(function() {
$('#grid').data('kendoGrid').addRow();
});
});
</script>
</head>
<body>
<div id="grid"></div>
<button id="add">add</button>
</body>
</html>
running the same problem, didn't find any workaround in internet, so after digging in kendo sources found workaround that seems to be working, but only with full datasource refresh
so, scenario is next:
add item to data array
set grid.dataSource._skip = 0;
refresh dataSource like grid.dataSource.data(data);
refresh scroll like $("#grid .k-scrollbar-vertical").scrollTop(0);
I've updated fiddle: http://jsfiddle.net/rDPBu/7/
<button id="add">addRow - not working</button>
<button id="add-top">add top</button>
<button id="add-bottom">add bottom</button>
<div id="grid"></div>
var data = [];
for(var i = 0; i < 100; i++) {
data.push({
check: i + 1,
ip: '10.1.201.3'
});
}
var grid = $('#grid').kendoGrid({
height: 300,
dataSource: {
data: data,
pageSize: 10,
schema: {
model: {
id: "check",
ip: "ip"
}
}
},
columns: [
{ field: "check" },
{ field: "ip" }
],
editable: true,
scrollable: {
virtual: true
}
}).data('kendoGrid');
var scroller = $("#grid .k-scrollbar-vertical");
$('#add').click(function () {
grid.addRow();
});
$('#add-top').click(function () {
data.splice(0,0,{check: 0, ip: '1.1.1.1'});
grid.dataSource._skip = 0; // fix databind
grid.dataSource.data(data);
scroller.scrollTop(0); // should refresh scroll
});
$('#add-bottom').click(function () {
data.push({check: 999, ip: '9.9.9.9'});
grid.dataSource._skip = 0; // fix databind
grid.dataSource.data(data);
scroller.scrollTop(scroller.prop("scrollHeight")); // should refresh scroll
});
Try to build up at this fiddle: http://jsfiddle.net/vojtiik/rDPBu/3/
var grid = $('#grid').kendoGrid({
height: 300,
dataSource: {
data: [
{check: 1,ip: "10.1.201.3"},
{check: 2,ip: "10.1.201.3"},
{check: 3,ip: "10.1.201.3"},
{check: 4,ip: "10.1.201.3"},
{check: 5,ip: "10.1.201.3"},
{check: 6,ip: "10.1.201.3"},
{check: 7,ip: "10.1.201.3"},
{check: 8,ip: "10.1.201.3"}
],
schema: {
model: {
id: "check",
ip: "ip"
}
}
},
columns: [
{ field: "check" },
{ field: "ip" }
],
editable: true,
scrollable: {
virtual: true
}
}).data('kendoGrid');
$('#add').click(function () {
grid.addRow();
});
EDIT :
Answer from Kendo support :
Adding new elements to a grid with virtual scrolling enabled is not a supported setup. Please keep in mind that you can always submit it in our feedback forum, so it can be taken into consideration for our future releases.
I am using a Kendo UI grid, which looks like this:
function refreshGrid()
{
$(".k-pager-refresh.k-link").click();
}
var editWindow;
var fields= {FullName: {type: "string"}, Email: {type: "string"}, LogCreateDate: {type: "date"}};
var gridColumns =
[{
width: 90,
command: {
name: "edit",
text: "Edit",
click: function(e) {
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
editWindow = $("#edit").kendoWindow({
title: "Edit User",
modal: true,
visible: false,
resizable: false,
width: 800,
height: 400,
content: 'myediturl' + dataItem.ID
});
editWindow.data("kendoWindow").center().open();
return false;
}
}
},
{
width: 90,
command: {
name: "delete",
text: "Delete",
click: function(e) {
//alert(this.dataItem($(e.currentTarget).closest("tr")).ID);
var id = this.dataItem($(e.currentTarget).closest("tr")).ID;
if (confirm("Are you sure you want to delete this user?"))
{
$.ajax({
type: 'POST',
url: '#Url.Action("deleteuser","admin",null, "http")' + "/" + this.dataItem($(e.currentTarget).closest("tr")).ID,
success: function (param) { refreshGrid(); },
async: false
});
}
return false;
}
}
},
{
field: "FullName",
title: "Full Name",
type: "string"
},
{
field: "Email",
title: "Email",
type: "string"
},
{
field: "LogCreateDate",
title: "Created",
type: "date",
template: '#= kendo.toString(LogCreateDate,"MM/dd/yyyy") #'
}];
//getSorts the columns of the grid
function getColumns() {
//Parsing the set of columns into a more digestable form
var columns = "";
for (var col in gridColumns) {
if (!!gridColumns[col].field)
{
if (columns.length > 0) {
columns += ";";
}
columns += gridColumns[col].field + "," + gridColumns[col].type;
}
}
return columns;
}
function getSorts(sortObject) {
if (!(sortObject)) {
return "";
}
//Getting the row sort object
var arr = sortObject;
if ((arr) && (arr.length == 0)) {
return "";
}
//Parsing the sort object into a more digestable form
var columnSet = getColumns();
var returnValue = "";
for (var index in arr) {
var type = "";
for (var col in gridColumns) {
if (gridColumns[col].field === arr[index].field) {
type = gridColumns[col].type;
}
}
returnValue += ((returnValue.length > 0) ? (";") : ("")) + arr[index].field + "," + (arr[index].dir === "asc") + "," + type;
}
return returnValue;
}
var grid;
$(function () {
$("#grid").kendoGrid({
dataSource: {
transport: {
read: {
url: "mydatasourceurl",
type: "POST",
},
parameterMap: function (data, type) {
data.filters = JSON.stringify(data.filter);
data.columns = JSON.stringify(getColumns());
data.sorts = JSON.stringify(getSorts(data.sort));
console.log(data);
return data;
}
},
schema: {
fields: fields,
data: "Data",
total: "Total"
},
pageSize: 10,
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
toolbar: [{
name: "Add",
text: "Add new record",
click: function(e){console.log("foo"); return false;}
}],
height: 392,
groupable: false,
sortable: true,
filterable: true,
pageable: {
refresh: true,
pageSizes: true
},
columns: gridColumns
});
grid = $("#grid").data("kendoGrid");
});
My create toolbar action is not triggered on click. How can I resolve this problem, is Kendo UI able to handle toolbar click events? The best solution I came up with looks like this:
$(".k-button.k-button-icontext.k-grid-add").click(function () {
//If the window doesn't exist yet, we create and initialize it
if (!grids[gridContainerID].addWindow.data("kendoWindow")) {
grids[gridContainerID].addWindow.kendoWindow({
title: "Add " + entityName,
width: "60%",
height: "60%",
close: onClose,
open: onAddOpen,
content: addUrl
});
}
//Otherwise we just open it
else {
grids[gridContainerID].addWindow.data("kendoWindow").open();
}
//Centralizing and refreshing to prepare the layout
grids[gridContainerID].addWindow.data("kendoWindow").center();
grids[gridContainerID].addWindow.data("kendoWindow").refresh();
return false;
});
Thanks in advance.
Instead of using that complex selector use the one that Kendo UI creates from name:
toolbar: [
{
name: "Add",
text: "Add new record",
click: function(e){console.log("foo"); return false;}
}
],
and then:
$(".k-grid-Add", "#grid").bind("click", function (ev) {
// your code
alert("Hello");
});
In kendogrid docs here shows that there is no click configuration for grid toolbar buttons like grid.colums.commands.
To solve this problem you can reference following steps:
create a template for toolbar
<script id="grid_toolbar" type="text/x-kendo-template">
<button class="k-button" id="grid_toolbar_queryBtn">Query</button>
</script>
apply tempate to toolbar
toolbar:[{text:"",template: kendo.template($("#grid_toolbar").html())}]
add event listener to button
$("#grid_toolbar_queryBtn").click(function(e) {
console.log("[DEBUG MESSAGE] ", "query button clicked!");
});