Grid editing in Kendo - kendo-ui

I hava a kendo grid which is set to be editable. It is working fine. all I need is to show a empty row in my grid regardless of any items present or not. This editable row should always come. for that I have searched various questions here also but none of them is working except the below:
$("#Grid").kendoGrid({
dataSource: TableDataSource,
autoBind: true,
scrollable: true,
sortable: {
allowUnsort: false
},
pageable: {
refresh: true,
buttonCount: 5,
pageSizes: 5
},
noRecords: {
template: "No records found."
},
dataBound : function () {
var firstItem = this.dataSource.view()[0];
if (firstItem.isNew() == false) {
firstItem.isNew();
this.addRow();
}
},
editable: true,
But here the problem is that it only shows a new row if grid have atleast one record coming from database . If Grid is empty, it is not adding a row in grid.
If I remove if condition , then the grid goes into infinite loop and crashes the browser.
I also tried this in document.ready but there is no success. Grid just don't respond
$(function(){
var grid = $("#Grid").data("kendoGrid");
grid.dataSource.insert( {} );//Not working
grid.addRow(); // Not working
});

Related

Kendo headerTemplate

I am trying to build this dojo with the headerTemplate and the columns title and data fields under it but I am not sure what I am doing wrong I am not getting any errors so its hard to understand what is happening?
https://dojo.telerik.com/#mcdevittnccn/iNinebUm
I would suggest a bit different approach here. Problem is that your data is a complex nested object (an object with an array of objects - basically grid inside grid). Kendo data source best works with flattened data. If you can't change data you can use the kendo grid detailInit event so every object array has an inner table with data. Something like this:
$(document).ready(function () {
$("#kendogrid").kendoGrid({
dataSource: {
data: data,
pageSize: 10
},
pageable: true,
scrollable: false,
persistSelection: true,
toolbar: ["search"],
search: {
fields: ['Name']
},
sortable: true,
columns: [
{
field: "Name",
title: "Name"
}
],
detailTemplate: '<div class="grid"></div>',
detailInit: function (e) {
e.detailRow.find(".grid").kendoGrid({
dataSource: e.data.PanelsMeetingViewModel
});
}
});
});
Example: Kendo grid detail init
Note: because of the inner table quick search will not work.

Kendo Grid Custom Flter Set Filter Value Programmatically

I am trying to programmatically set the filter value of a Kendo Grid Custom Filter. I'm applying my new filter values like:
gridOptions.dataSource.filter = [
{
field: 'MyField',
operator: 'eq',
value: newTextValue
}
];
My field definition in the grid options look like:
{
width: '140px',
title: 'MyFieldTitle',
field: 'MyField',
filterable: getFieldFilter()
}
With the following filter:
function getFieldFilter() {
return {
cell: {
template: function (args) {
var element = args.element;
element.kendoComboBox({
dataSource: {
transport: {
read: 'api/Items'
}
},
valuePrimitive: true,
dataTextField: 'Description',
dataValueField: 'Code'
});
},
showOperators: false
}
};
}
If I apply the filter as shown above, it only works after I click the kendoComboBox in the column and click outside of it again.
My initial thought was that kendo grid would not apply the dataValueField and just set the dataTextField. When I was checking the requests kendo grid is sending to the server, I saw that it was sending to value stored in the kendoComboBox itself (text) and not the value behind it.
If I select something in the kendoComboBox from the UI, everything works just fine. But if I set it programmatically like above, it doesn't.
Do I need to refresh some kind of state to make the kendoComboBox refresh its internal value or how do I solve this issue?
EDIT:
What I'm trying to do, is getting the value of the kendoCombobox from the grid.
var currentlyAppliedFilters = grid.dataSource.filter().filters;
for (var filter of currentlyAppliedFilters) {
if (filter.field === 'MyField') {
var currentlyApplied = filter.value;
}
}
So the code above, would give me the Description property of the items in the kendoCombobox, but what I actually want to get it the Code property.
Initially when the dataSource do not have a filter, the cell filter need a option label. so that the 1st value does not appear as selected.
eg : dojo example with optionLabel
args.element.kendoDropDownList({
dataSource: args.dataSource,
optionLabel: "Select a color...",
dataTextField: "color",
dataValueField: "color",
valuePrimitive: true
});
if you you need the grid to filter when binding, a default filter should be added to the dataSource
eg: dojo example with DataSource Filter
dataSource: {
data:[ { color: "#ff0000", size: 30 }, { color: "#000000", size: 33 }] ,
filter: { field: "color", operator: "eq", value: "#ff0000" }
}
Hope this helps.

How I can sort whole data in different pages of my kendo grid?

I'm using a kendo gird. When I sort my grid, It doesn't sort next page data. It is only sorted on first page. I want to sort whole data in the grid. How can I do it??
$("#ProductGrid").kendoGrid({
columns: [
{ field: "ProductID", title: 'Product Id' ,width:50},
{ field: "ProductName", title: 'Product Name' },
{ field: "Price", title: 'Price' },
],
groupable: true,
sortable: true,
pageable: true,
dataBound: function () {
this.expandRow(this.tbody.find("tr.k-master-row").first());
},
scrollable: true,
filterable: true,
dataSource: new kendo.data.DataSource({
transport: {
read: "../api/Product/FindByPartyIDForGrid?partyID=" + PartyID
},
serverPaging: true,
serverSorting: true,
pageSize: 50,
schema: {
data: "Data",
total: "Count"
}
})
});
My server side method
[System.Web.Http.AcceptVerbs("GET", "POST")]
[System.Web.Http.HttpGet]
[ActionName("FindByPartyIDForGrid")]
public Responce FindByPartyIDForGrid(string partyID)
{
int take = httpRequest["take"] == null ? 10 : int.Parse(httpRequest["take"]);
int skip = httpRequest["skip"] == null ? 0 : int.Parse(httpRequest["skip"]);
var content = new ProductBS().FindByPartyID(Convert.ToInt32(partyID));
if (content != null)
{
return new Models.Responce(content.Skip(skip).Take(take).ToArray(), content.Count());
}
else
{
return new Responce(new Array[0], 0);
}
}
Seems like this is not a client side (kendo) issue. Kendo grid is configured correct as I can see. In your FindByPartyIDForGrid method you need to do the sorting and return relevant page correctly.
Check your server logic, If you can post it here we can have a look in to it.
EDIT
Seems like you haven't handle the sorting in the server,you have two options,
1.You can do it using Odata protpcol
2. You can do it by handling sorting yourself,
This occurs because you have enabled serverSorting. Then you should perform the sorting yourself.
If you don't bind the grid to lots items you can use client-side sorting. Simply remove the serverSorting: true option of the data source.

Is a Footer row in a jqgrid selectable/clickable?

I have a jqgrid that has main rows and a footer row (with userdata loaded) and then a formatter that alters the data in the cells to be linkable. The cells in the main body can be clicked and the onCellSelect event will capture the click. However, clicking on data in the footer row does not seem to fire off the onCellSelect event. How do I capture a select/click event in the footer row? Below is the script for the jqgrid.
$('#jqgSummaryResults').jqGrid({
datatype: 'json',
mtype: 'GET',
url: 'some action',
postData: { 'criteria': function () {
some function}},
rowNum: 100,
rowList: [],
pager: '#jqgpSummaryResults',
viewrecords: true,
sortorder: 'asc',
sortname: 'DateField',
width: 1250,
height: 350,
shrinkToFit: true,
gridview: true,
footerrow: true,
userDataOnFooter: true,
onCellSelect: function (rowid, iCol, cellcontent, e) {
var selectedDate = rowid;
savedMailDueDateString = rowid;
var selectedColumn = iCol;
...
},
loadComplete: function (data) {
...
},
colNames: ['DateField',
'Total Jobs',
...
'% Not Mailed'],
colModel: [
{ name: 'DateField', index: 'DateField', align: 'left' },
{ name: 'TotalJobs', index: 'TotalJobs', align: 'left', formatter: hyperlinkColumnFormatter },
...
{ name: 'PercentNotMailed', index: 'PercentNotMailed', align: 'left', formatter: hyperlinkColumnFormatter },
]
}).navGrid('#jqgpSummaryResults', {
excel: false,
edit: false,
add: false,
del: false,
search: false,
refresh: false
});
Thanks for the assistance.
While I didn't see any way to have jqGrid respond to select (doesn't even seem that that footer is selectable) or a click. The footer row is specified by a ui-jqgrid-sdiv class. You could attach a click event handler as below.
$('.ui-jqgrid-sdiv').click(function() {alert('Bong')});
Edit: In response to Gill Bates question to add a footer event but only on a single cell the selector would be:
$('.ui-jqgrid-sdiv').find('td[aria-describedby="GridName_ColumnName"]').click(function() { alert("Bong");});
GridName_ColumnName is the format for all the footer td aria-describedby, and you can see the exact name via firebug element inspector (or any of it's equivalents).
jqGrid registers click event on main <table> of the grid, but it calls onCellSelect not always. First of all (see here) it tests some additional conditions and then returns (ignore click event) if the conditions failed. For example if one clicks on grouping headers of the grid the callback onCellSelect will not be processed.
The problem with footer row because it exists outside of the grid. The main <table> element are placed inside of div.ui-jqgrid-bdiv, but the footer is inside of another table which is inside of div.ui-jqgrid-sdiv. One can examine the HTML structure of jqGrid using Developer Tools of Internet Explorer, Google Chrome, Firebug or other. One will see about the following
The main <table> element (<table id="list"> in the picture above and which get the class "ui-jqgrid-btable") and another table element with the footer (which get the class "ui-jqgrid-ftable") are separate.
So the fist answer of Mark on your question was correct. If one has multiple grids on the page one could specify footer of specific grid using
var $grid = $('#jqgSummaryResults'); // one specific grid
.... // here the grid will be created
$grid.closest(".ui-jqgrid-view").find(".ui-jqgrid-sdiv").click(function() {
// do in case of the footer is clicked.
var $td = $(e.target).closest("td"),
iCol = $.jgrid.getCellIndex($td); // or just $td[0].cellIndex,
colModel = $grid.jqGrid("getGridParam", "colModel");
// $td - represents the clicked cell
// iCol - index of column in footer of the clicked cell
// colModel[iCol].name - is the name of column of the clicked cell
});
P.S. In the old answer are described many other elements of the grid. The descriptions are not full, but it could be probably helpful.
Here little implementation of this problem, i'm new in jquery and jqgrid, but i had same problem and thanks two posts above of #Oleg and #Mark, Im implemented something like that:
//Raport1Grid - name of my jqgrid
//endusers, adminusers,decretusers - name of my rows in colModel
//Raport1Grid_endusers - GridName_ColumnName
var endUsers = $("[aria-describedby='Raport1Grid_endusers']").click(function(){
//remove previous style of selection
$('.ui-jqgrid-ftable').find('.selecteClass').removeClass('selecteClass');
//set selection style to cell
$(endUsers).addClass('selecteClass');
});
//Also can get value of selectedCell
var qwer = $("[aria-describedby='Raport1Grid_endusers']").text();
alert(qwer);
Demo here
http://jsfiddle.net/Tobmai/5ju3py83/

jqgrid open subgrid only if there is some data

here is declarations of my subgrid:
subGrid : true,
subgridtype: 'json',
subGridUrl: 'manuf_subgr.php',
subGridModel: [{ name : ['Package','Sticker','Manufacturer'],
width : [85,50,100],
params: ['Catalogue']
}
],
gridComplete: function() {
var timeOut = 50;
var rowIds = $("#schedule").getDataIDs();
$.each(rowIds, function (index, rowId) {
if(rowId.row_cnt != 0){
setTimeout(function() {
$("#schedule").expandSubGridRow(rowId);
}, timeOut);
timeOut = timeOut + 200;
}
});
}
what I expect to happen is this line if(rowId.row_cnt != 0) preventing opening a subgrid if there is no data returned from json... yet all grids are open regardless...
can someone help to implement stop for opening empty subgrids?
full code:
jQuery("#schedule").jqGrid({
url:'sched.php',
datatype: "json",
mtype:'GET',
colNames:['Street_Date','Label','Catalogue', 'Artist', 'Title','UKDP','UPCEAN','format'],
colModel:[
{name:'Street_Date',index:'Street_Date desc, ID', sorttype:"date", formatter:'date', formatoptions: {newformat:'d/m/Y'}, width:75},
{name:'label',index:'label', width:100,align:"center"},
{name:'Catalogue',index:'Catalogue', width:85},
{name:'Artist',index:'Artist', width:120},
{name:'Title',index:'Title', width:250},
{name:'UKDP',index:'UKDP', width:35, align:"right", formatter:"number", sorttype:"float"},
{name:'UPCEAN',index:'UPCEAN', width:120, align:"center"},
{name:'format',index:'format', width:70, sortable:false}
],
height: "100%",
rowNum:20,
rowList:[10,20,30,50,100],
sortname: 'id',
viewrecords: true,
sortorder: "desc",
jsonReader : {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: true,
cell: "cell",
id: "id",
userdata: "userdata",
subgrid: {root:"rows", repeatitems: true, cell:"cell" }
},
pager: '#schedule_pager',
caption:"Release Schedule",
grouping:true,
groupingView : {
groupField : ['Street_Date']
},
subGrid : true,
subgridtype: 'json',
subGridUrl: 'manuf_subgr.php',
subGridModel: [{ name : ['Package','Sticker','Manufacturer'],
width : [85,50,100],
params: ['Catalogue']
}
],
gridComplete: function() {
var timeOut = 50;
var rowIds = $("#schedule").getDataIDs();
$.each(rowIds, function (index, rowId) {
if(rowId.row_cnt != 0){
setTimeout(function() {
$("#schedule").expandSubGridRow(rowId);
}, timeOut);
timeOut = timeOut + 200;
}
});
},
onSelectRow: function (rowId) {
$("#schedule").jqGrid ('toggleSubGridRow', rowId);
}
});
You write in the comment that you are newbie and it's the second day when you use it. jqGrid is relatively complex and your first example which you try to implement seems to me too complex for newbie. You try to load fill jqGrid with the data from the database and do grouping and subgrid in one grid.
What you try to implement in your demo can be solved by usage of expandOnLoad: true property of the subGridOptions option:
subGridOptions: {expandOnLoad: true}
You can see the feature on the official demo disguised under "Hierarchy" / "Expand all Rows on load". There are one important problem which I described in the answer. The problem is shortly the following: internal implementation of Ajax requests used in jqGrid prevent (skip) Ajax requests when another pending (not yet answered by the server) are working (see .grid.hDiv.loading in the places of the code here, here in the subgrid module and here, here and here). Neither expandOnLoad: true nor your current implementation can grantee that new Ajax request will be started during previous one still not responded. So you can have not all subgrids opened. You main question: "how to prevent opening of empty subgrids or how to hide it?", I find the second (and less important) question. Even if you see currently that your web site opens all subgrids it can be that access to the same site from more far place from the internet will follow opening of one or some subgrids only.
So I think that you should either change the design of your web page (change what you want to display in subgrids) or change the implementation so that you construct a queue with the list of subgrids which should be opened and you will open the next grid only after the previous one will be opened.
Alternatively you can includes the data for all subgrids in the response for the main grid. In the case you should use subGridRowExpanded callback to fill the grids as subgrid as grid. You you would use no caption and no pager option in the subgrids you will be get the same look as with the standard subgrids. Additionally you will have much more flexibility in the options. I personally prefer to subgrid as grid.

Resources