I have a Kendo grid in my application and I am binding data to it through REST call. When the grid load first time, the buttons doesn't show up. Below is the example:
There are 400+ items in the grid, currently it is configured to show only 50 items per page. But the problem is I am not able to see options to visit second/next page.
Option of second page is visible when I change items per page. Like If I change option from 50 - 100. I am able to see other page number.
This is the second Problem. Page number appears in vertical way instead of horizontal.
I need help in solving below issues:
When Page Load pagination options should be displayed as they are suppose to be.
Pagination numbers should appear in horizontal way not in vertical way.
Below is my code snippet:
$scope.mainGridOptions = {
editable: true,
pageable: {
pageSizes: [15,25,50,100]
},
navigatable: true,
sortable: true,
filterable: true,
dataSource: {
type: "odata",
pageSize: 50,
batch: false,
requestEnd: function(e) {
if (e.type != 'read')
{
$('#grdItemizations').data('kendoGrid').dataSource.read();
}
},
schema: {
model: {
id: "Id",
fields: {
Id: { type: "number", editable: false },
Title: { type: "string",editable: false }
}
},
data: function (data) {
return data.d && data.d.results ? data.d.results : [];
}
},
transport: {
parameterMap: function (data, type) {
if (type != "read") {
var strIfy = kendo.stringify({
"__metadata": type != "create" ? { "type": },
"Title": data.Title,
"Id": type != "create" ? data.ID : undefined
});
return strIfy;
}
return kendo.data.transports["odata"].parameterMap.apply(this, arguments);
},
read: {
},
update: {
},
create: {
},
error: function (e) {
alert("Status: " + e.status + "; Error message: " + e.errorThrown);
}
},
},
columns: [
{ field: "Id", title: "ID" , width: "60px"},
{ field: "Title", title: "Analytic Inventory Description" , width: "220px"}
]
}
Any hint, help is really appreciated.
There can be other issues since you have not posted complete code.
First of all , I suspected there was was something off(missing css,incorrect version of kendo css referred, murtiple css conflicting) on css side since that deals with the presentation of grid .
Then i pulled up a demo and removed these css files
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.1.118/styles/kendo.common-bootstrap.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.1.118/styles/kendo.bootstrap.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.1.118/styles/kendo.bootstrap.mobile.min.css" />
and see the image below surprisingly the result are kind of little similar i can see pagination button in a vertical format.
Please double check something is off on css side(check reference to kendo grid css by looking at viewsource page) if that does not solve problem make sure you post the complete code
Related
I'm using kendo-ui grid for AngularJs and want to activate virtualization of remote data functionality. For testing I have set pageSize: 5.
Below is description of virtualization of remote data from telerik site:
There are cases when you may need to operate with large amount of data
in the grid, and fetching and processing this data at once would
impose a performance penalty due to limited browser resources.
Luckily, the Kendo UI grid has a solution called data virtualization
that alleviates any slowdowns when operating with huge volumes of
data. When enabled via the scrollable->virtual configuration option,
it displays a vertical scrollbar for the grid content and renders only
the number of items set via the pageSize property of the grid data
source. After you drag the scrollbar and the pageSize is exceeded, it
makes automatic requests to retrieve and render the next set of grid
rows. Both local and remote data are supported with the grid
virtualization feature, whereas in this demo the records are obtained
from a remote endpoint.
Also I have set following:
HTML:
<div kendo-grid k-options="mainGridOptions" id="historyGrid" style="width: auto;"></div>
JS for grid:
var vm = $scope;
vm.viewMode = {
mainGridOptions: {
visible: true
}
};
vm.mainGridOptions = {
columns: [
// here columns
],
onRegisterApi: function (gridApi) {
vm.gridApi = gridApi;
},
dataSource: {
schema: {
model: {
fields: {
YearBalance: { type: 'number' },
Typezalezh: { type: 'string' },
License: { type: 'string' },
ObjectName: { type: 'string' },
ZalezhName: { type: 'string' },
PlastName: { type: 'string' },
Category: { type: 'string' },
Parameter: { type: 'string' },
LastVal: { type: 'string' },
Val: { type: 'string' },
Operation: { type: 'string' },
EndT: { type: 'date' }
}
}
},
pageSize: 5,
transport: {
read: function(e) {
dataservice.getImportResultReport().then(function(data) {
e.success(JSON.parse(data));
console.log(data);
});
}
}
},
serverPaging: true,
height: screen.height - 330,
minwidth : 1190,
batch: true,
scrollable: {
virtual: true
},
sortable: true,
serverSorting: true,
filterable: {
extra: false,
operators: {
string: {
// here filters
},
number: {
// here filters
},
date: {
// here filters
}
}
}
};
On telerik site (Official website), it says that nothing more needs to be done.
On scrolling, I should see a request to the server which in my case should be a dataservice.getImportResultReport() call. But this does't happen. This function is called only once and all data is returned.
May be it's occurring because I have not set type: "odata"? But I use data source of another type.
How to use this functionality?
Add k-scrollable directive as follows in your html that renders your kendo grid:
<div kendo-grid k-data-source="mainGridOptions" k-scrollable="{virtual:true}"></div>
Also you have to use k-data-source directive for your dataSource. Hope it helps.
Working demo plunkr
The problem I'm having is exactly what I said in the title. When I step through my application in the debugger it properly sets everything that needs to be set, but when I just let it go through on its own, it never loads data on the initial attempt, but if i go back and click the same thing again, or any thing else that has to send data to this grid, it will forever work. Even if I go to a page that empties everything in the grid and then go back to one that shows data again.
To me it sounds like a timing issue, but using $timeout() before the data calls doesn't seem to be working. And I set up a broadcast that should only be called after all the data is pulled in and set, and only then should it go to the code for the kendo grid and start painting it on the page.
Like I said stepping through this code line by line on the initial load of the page, it works exactly as it should and pulls in all data that it needs, but letting it just run without me doing that, it never does.
here is hopefully enough code to go off of.
Here is the code for my grid:
$scope.$on('loadRxHistoryGrids', function () {
console.log('user id of ' + pServ.patientId.get());
$scope.activeHistoryGrid = {
pageable: {
pageSizes: [5, 10, 15, 20],
},
dataSource: new kendo.data.DataSource({
type: 'aspnetmvc-ajax',
contentType: "application/json; charset=utf-8",
transport: {
read: {
url: function () {
var x = pServ.patientId.get();
return "api/rx/ActiveRxHistory/" + pServ.patientId.get();
},
dataType: "json",
type: "POST"
},
},
pageSize: 5,
schema: {
model: {
fields: {
rxId: { type: "number" },
refillsLeft: { type: "number" },
shortName: { type: "string" },
unitsRemaining: { type: "number" },
dispenseRefillQuantity: { type: "number" },
description: { type: "string" },
shipDate: { type: "date" }
},
},
data: function (data) {
if (data != undefined) {
$scope.ActiveHistoryCount = data.length;
return data;
} else { return []; }
},
total: function (data) {
return data.length;
},
},
}),
serverPaging: true,
serverSorting: true,
serverFiltering: true,
columns: [
{ hidden: true, field: "rxId"},
{ field: "shortName", title: "DRUG NAME"},
{ field: "refillsLeft", title: "REFILLS LEFT", width: "16%", template: '#= (refillsLeft == null) ? " " : kendo.toString( refillsLeft, "n0")#', attributes: { style: "text-align:left" } },// template: '<div style="text-align:left">#= ((unitsRemaining == null) || (dispenseRefillQuantity == null)) ? " " : kendo.toString(unitsRemaining / dispenseRefillQuantity, "n5")#</div>' },
{ field: "description", title: "STATUS", width: "14%", template: '<div style="text-align:left">#= (description == null) ? " " : description#</div>' },
{ field: "shipDate", title: "SHIPPED DATE", width: "15%", template: '#= (shipDate == null) ? " " : kendo.toString(kendo.parseDate(shipDate), "MM/dd/yyyy") #' }
],
groupable: false,
scrollable: true,
selectable: true,
resizeable: true,
sortable: true,
}
Here is the other code where the broadcast is being sent:
$scope.$on('loadPatientProfileData', function () {
//A lot of data gets and sets are being done here for other things on the
//page, all data is being set in the grid datasource itself
setTimeout(function () {
$rootScope.$broadcast('patientProfile-DataPullFinish');
$rootScope.$broadcast('loadRxHistoryGrids');
}, 100);
});
I have a Kendo UI grid, which is bound to an KendoObservableArray. I am using inline edit mode. And my options are declared as below :
valueMapCtrl.lookupMappingDetails = new kendo.data.ObservableArray([]);
valueMapCtrl.gridOptions = {
dataSource: new kendo.data.DataSource({
type: "json",
transport: {
read: function (options) {
options.success(valueMapCtrl.lookupMappingDetails);
},
update: function (options) {
console.log("Update", options);
options.success(options.data);
},
create: function (options) {
console.log("Create", options);
options.data.mappingId = mappingId;
mappingId = mappingId + 1;
options.success(options.data);
},
destroy: function (options) {
console.log("Delete", options);
options.success(options.data);
},
parameterMap: function (options, type) {
// this is optional - if we need to remove any parameters (due to partial OData support in WebAPI
console.log(options, type);
if (operation !== "read" && options.models) {
return JSON.stringify({models: options});
}
},
},
change: function (e) {
console.log("change: " + e.action);
// do something with e
},
error: function (e) {
// handle error
alert("Status: " + e.status + "; Error message: " + e.errorThrown);
},
//data: valueMapCtrl.dynamicData,
schema: {
model: {
id: "mappingId",
fields: {
mappingId: {editable: false, nullable: false, defaultValue: 0},
Col1: {
type: "string",
validation: {
required: true
}
},
Col2: {
type: "string",
validation: {
required: true
}
}
}
}
},
pageSize: 10,
batch: false
}),
columns: [{
field: "col1",
title: "Column 1"
}, {
field: "col2",
title: "Column 2"
}, {
command: /*"destroy"*/ ["edit", "destroy"],
title: " ",
width: "200px"
}],
selectable: "multiple cell",
allowCopy: "true",
//save: function (e) {
// console.log("Save", e);
//},
toolbar: ["create"],
height: 300,
navigatable: true,
filterable: true,
sortable: true,
pageable: true,
editable: "inline"
};
Add record : create fires correctly
Delete record: destroy fires correctly
Update record : nothing happens, no error, all I see in change event sync() action.
But If I declare save as well in my options, that fires correctly.
save: function (e) {
console.log("Save", e); //This fires on each update
},
I am not sure what is wrong in above declaration; browsed through a lot of forums/questions for similar issue but could not get it working. Any help ?
I was able to get it working, posting here in case anyone gets the same issue.
valueMapCtrl.lookupMappingDetails = new kendo.data.ObservableArray([]);
I changed this observable array to normal array and things worked fine after that :
valueMapCtrl.lookupMappingDetails =[];// new kendo.data.ObservableArray([]);
Also, with observable array, I was facing another issue; where cancelling of edit was removing ALL ROWS from the grid. That also worked correctly after this change. Not sure of the reason though and couldn't find any explanation in telerik docs (Whatever I could search).
I've got a datagrid configured as follows:
<script>
angular.module("KendoDemos", [ "kendo.directives" ]);
function MyCtrl($scope) {
$scope.mainGridOptions = {
dataSource: {
transport: {
read: {
url: "http://localhost:8090/rest/mycodeapi/Salesman?app_name=mycode&fields=FirstName%2C%20LastName&include_count=true",
dataType : 'jsonp',
type: 'GET',
beforeSend: function (req) {
req.setRequestHeader('Authorization', 'b3pilsnuhsppon2qmcmsf7uvj6')
}
},
parameterMap: function(data, type) {
if (type == "read") {
// send take as "$top" and skip as "$skip"
return {
order: data.sort[0]['field'] + ' ' + data.sort[0]['dir'],
limit: data.pageSize,
offset: data.skip
};
}
}
},
schema: {
data : 'record',
total: 'meta.count'
},
pageSize: 5,
serverPaging: true,
serverSorting: true,
sort: { field: "SalesmanID", dir: "asc" }
},
sortable: true,
pageable: true,
mobile: 'phone',
columns: [{
field: "FirstName",
title: "First Name"
},{
field: "LastName",
title: "Last Name"
}]
};
}
</script>
Problem is: on 1st click of the any column, say FirstName, it sorts by ascending order which is fine.
On 2nd click it sorts by descending: still the expected behaviour.
On the 3rd click however, nothing happens and the console reveals "Uncaught TypeError: Cannot read property 'field' of undefined ". This means something happens to the data.sort array after the 2nd consecutive click.
Would appreciate any pointers.
On third click the sorting is removed. You can modify your script like following:
if (type == "read") {
var params = {
limit: data.pageSize,
offset: data.skip
};
if (data.sort && data.sort.length > 0)
params.order = data.sort[0]['field'] + ' ' + data.sort[0]['dir'];
return params;
}
I know this is a bit late, but I was facing the same challenge, and this is what I did to resolve the issue.
Change
sortable: true,
to
sortable: {
allowUnsort: false
},
I have a grid, inside of some column of which I have created a combobox editing UI, using columns.editor function.
My goal is every time a user selects some value from the combobox -while populating a newly created grid record-, this value to be
removed from the list options of a next record's combobox.
One of the things i've tried is shown below:
function equipmentDropDownEditor(container, options) {
var equipmentComboBox = $('<input id="equipmentDropDownEditor" required data-text-field="name" data-value-field="name" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: equipmentTypesDS,
dataBound: function(e) {
var equipmentData = e.sender.dataSource.data();
if(currentlyInsertedEquipmentTypes.length > 0){
for(var i=0;i<currentlyInsertedEquipmentTypes.length;i++){
$.each( equipmentData, function( index, selectedEquipmentData ) {
if (selectedEquipmentData.name == currentlyInsertedEquipmentTypes[i]){
var dataItem = e.sender.dataSource.at(index);
console.log("dataItem: " + dataItem.name + " is being removed");
e.sender.dataSource.remove(dataItem);
}
});
}
}
}
});
}
I've created a global array variable named "currentlyInsertedEquipmentTypes" inside of which I hold all the user's already selected values
(for example if the user has created 2 records inside the grid and has selected "laptop" option in the combobox of the first and "workstation" option
in the combobox of the second --> currentlyInsertedEquipmentTypes = ["laptop", "workstation"] ).
Inside the combobox dataBound event I check whether the user has already selected values (currentlyInsertedEquipmentTypes.length>0)
and if he has, I locate the corresponding object inside the bound dataSource and I remove it, so that it wont be available in the next record's combobox list.
This is where the whole thing crashes even though the data item removal takes place.
Am i missing something that i should do after the data item removal? Should i rebind the datasource to the combobox in some way?
Any help would be much appreciated.
[EDIT]
---- The combobox datasource code
var equipmentTypesDS= new kendo.data.DataSource({
transport: {
read: {
url: "api/equipment_types",
type: "GET",
data: {
//"equipment_category": 1
},
dataType: "json"
}
},
schema: {
data: "data",
total: "total"
}
});
--- the kendo grid code:
$("#popup_equipment").kendoGrid({
dataSource: {
schema:{
model:{
id: "equipment_type_id",
fields:{
equipment_type_id: { editable: false },
name: { }, //validation: {required: true}, defaultValue: "LAPTOP",
items:{ type: "number", defaultValue:1, validation: { required: true, min: 1} }
}
}
}
},
toolbar: ["create"],
columns: [
{ field: "name", title: "εξοπλισμός", width: "300px", editor: equipmentDropDownEditor, template: "#=name#" },
{ field: "items", title:"πλήθος", width: "80px"},
{ command: ["destroy"], title: " ", width: "100px" }
],
//editable: "inline",//true,
editable:{confirmation: false},
scrollable: false,
selectable: false
});
[EDIT 2]
$("#popup_equipment").kendoGrid({
dataSource: {
schema:{
model:{
id: "equipment_type_id",
fields:{
equipment_type_id: { editable: false },
name: { }, //validation: {required: true}, defaultValue: "LAPTOP",
items:{ type: "number", defaultValue:1, validation: { required: true, min: 1} }
}
}
}
},
toolbar: ["create"],
columns: [
{ field: "name", title: "εξοπλισμός", width: "60%", editor: equipmentDropDownEditor, template: "#=name#" },
{ field: "items", title:"πλήθος", width: "20%"},
{ command: ["destroy"], title: " ", width: "20%" }
],
editable:{confirmation: false},
scrollable: false,
selectable: false,
save: function(e){
console.log("GRID SAVE EVENT! ", e);
var equipment_name = e.values.name;
equipmentTypesDS.get(equipment_name).used = true;
console.log("equipmentTypesDS", equipmentTypesDS);
console.log("END OF GRID SAVE EVENT!");
}
});
function equipmentDropDownEditor(container, options) {
var equipmentComboBox = $('<input id="equipmentDropDownEditor" required data-text-field="name" data-value-field="name" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: equipmentTypesDS,
});
}
var equipmentTypesDS= new kendo.data.DataSource({
transport: {
read: {
url: "api/equipment_types",
type: "GET",
data: {
//"equipment_category": 1
},
dataType: "json"
}
},
schema: {
data: "data",
total: "total",
model:{
id: "name"
}
},
filter: { field: "used", operator: "neq", value: true }
});
I would suggest a different approach. Instead of removing the element filter it out.
Example: I define a DataSource with a list of Cities (your Inserted Equipment) as follow:
var cityDS = new kendo.data.DataSource ({
data : [
{ City : "Seattle", used : false },
{ City : "Tacoma", used : false },
{ City : "Kirkland", used : false },
{ City : "Redmond", used : false },
{ City : "London", used : false },
{ City : "Philadelphia", used : false },
{ City : "New York", used : false },
{ City : "Boston", used : false }
],
schema : {
model : {
id : "City"
}
},
filter: { field: "used", operator: "eq", value: false }
});
As you can see I added a field called used that simply says if that City is already used or not. And I set it as id of this DataSource. In addition, I set a filter saying that I only want those where used id equal (eq) to false.
The editor function is pretty much yours:
function cityDropDownEditor(container, options) {
var equipmentComboBox = $('<input required data-text-field="City" data-value-field="City" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: cityDS
});
}
but with no dataBound or any other event handler.
Finally in the Grid when I save a record, I filter that city from the list. Something like:
var grid = $("#grid").kendoGrid({
dataSource: ds,
editable : "popup",
pageable : true,
toolbar: [ "create" ],
columns :
[
{ field: "FirstName", width: 90, title: "First Name" },
{ field: "LastName", width: 200, title: "Last Name" },
{ field: "City", width: 200, editor : cityDropDownEditor }
],
save : function(e) {
console.log("e", e);
var city = e.model.City;
cityDS.get(city).used = true;
}
}).data("kendoGrid");
This might work if you start the Grid with no elements otherwise you would have to conveniently initialize the used field. It might require some additional code dealing with cases as changing the City but from your description, doesn't seem to be the case.
You can see this running here : http://jsfiddle.net/OnaBai/ZH4aD/