jqgrid not displaying option text after save - jqgrid

I have 3 editable dropdown columns in jqgrid, 2 dropdowns are populated dynamically onedit. Because values of those dropdown depends on selection of first. Grid row becomes editable as soon as row is selected & its configured to update the values after user clicks enter. Issue is after saving row, dropdown column 3 & 4 are not showing selected text in the grid. Cells are empty.
This is how both columns are setup
{
name: "FirstDrop", index: "FirstDrop", width: 180, align: "left", editable: true, formatter: 'select', edittype: "select", editoptions: {
value:"0:select;1:first,2:second", valuesToSelect: "0"
, dataEvents: [
{
type: 'change',
fn: function (e) {
//function that reload SecDrop based on value selected in this
}
}
]
}
},
{
name: "SecDrop", index: "SecDrop", width: 180, align: "left", editable: true, edittype:'select', formatter: 'select', editoptions: {
dataInit: function (elem) {
// function that appends options to "elem"
//$(elem).val(""); Select initial value here
}
}
}
So now, when I change selection in first dropdown, second dropdown is reloaded with new value. After selecting new value in second dropdown, upon saving, the column is empty. Instead it should show text value of selected option.
I get the value of the second column when I loop through all rows.
Not sure what I am missing here.
Any suggestions, is something missing, can same result be achieved using custom format option.

Not sure if this is a known issue in jqgrid v.4.7 But I figured out a hack, now handling the aftersave function to get the value of selected option and retrieving its corresponding text from the source json & assigning it to cell.

Related

How to implement my own "onCellClick" event handler

In my JQGrid I have check box column and drop Down drop down is created via edittype: 'select' and check boxes are created via "custom formatter" like this edittype: 'checkbox', formatter: returnCheckBox, I want to write my own "onChange" event.
So for I been able to write my "onchange" event for check box and it works fine but when I click some where else (not on check box) in check box cell and click back on check box it stop firing the "onchange" event. I think row select it causing problem how to stop it.
Here is what i am doing
$("#theGrid").jqGrid({
datatype: 'local',
sortname: 'value1',
sortorder: 'desc',
cellsubmit: 'clientArray',
editurl: 'clientArray',
cellEdit: true,
colNames: ['SName', 'SType', 'DName', 'DType', 'Nullable'],
colModel: [
{ name: 'SName', index: 'SName', width: 100 },
{ name: 'SType', index: 'Type', width: 100 },
{
name: 'DName',
index: 'DName',
width: 100,
editable: true,
edittype: 'select',
editoptions: { value: "1:ID;2:Name" },
},
{
name: 'DType',
index: 'DType',
width: 100,
editable: true,
edittype: 'select',
editoptions: { value: "1:BigInt;2:VarChar(50)" }
},
{
name: 'Nullable',
index: 'Nullable',
width: 100,
editable: true,
edittype: 'checkbox',
//formatter: "checkbox",
formatter: checkedStateChange,
sortable: false,
formatoptions: {disabled : false},
}
]
});
var gridData = [
{ SName: 'ID', SType: 'BigInt', DName: 'ID', DType: 'BigInt' },
{ SName: 'Name', SType: 'VarChar(50)', DName: 'Name', DType: 'VarChar(50)' },
];
for (var i = 0; i < gridData.length; i++) {
$("#theGrid").jqGrid('addRowData', gridData[i].value0, gridData[i]);
}
function checkedStateChange(cellvalue, options, rowObject) {
return '<input type="checkbox" class="gridCheckBox"/>';
}
$('.gridCheckBox').on('change',function(){
alert('I am in checkBoxChange method');
});
The code which you posted have really many small problems.
The problem with change exists because of at least two reasons. The first one: you have to place binding to change event inside of loadComplete callback of jqGrid. The current code bind change event only to existing checkboxs on the page. By sorting the grid for example the grid content will be rebuild and new checkboxs will be created. So all old binding will not work more. The next problem is modifying of checkboxs because of cell editing. If you click in the cell with the checkbox the old content will be destroyed and another checkbox will be created on the same place. The checkbox will have no change binding. After the user clicks on another cell the current cell will be saved. So the editing checkbox will be destroyed and new checkbox will be created in the same place with respect of formatter: "checkbox" or formatter: checkedStateChange. As the result the change event handler will be exist on the checkbox.
I personally don't see any reason why you use formatter: checkedStateChange (or formatter: "checkbox" with formatoptions: {disabled : false}) together with cell editing. It makes only problems. Much more consequent would be to use formatter: "checkbox" without formatoptions: {disabled : false} and just to use afterSaveCell callback of cell editing instead of "onchange" event.
Additional problems in your code:
The usage of name: 'SType', index: 'Type' is wrong because index value have to be the same as name value in case of usage datatype: "local". The current settings will don't make correct sorting or searching in the column SType. I strictly recommend you to remove all index properties from colModel
You use editoptions: { value: "1:BigInt;2:VarChar(50)" } in the DType column which seend be wrong. Correct value should be editoptions: { value: "BigInt:BigInt;VarChar(50):VarChar(50)" }. If you need to use value: "1:BigInt;2:VarChar(50)" then the input data should contains 1 and 2 values in DType column and you should use formatter: "select" additionally.
You can remove colNames option because it contains the same value like the values of name property of colModel.
You should never fill grid with data using addRowData called in the loop. Instead of that you should just move definition of gridData before creating of jqGrid and include data: gridData option in the grid.
The grid have no pager. Nevertheless the local paging still work and the pager site is 20 (it's default value of the option rowNum). Using addRowData you can fill more es 20 rows, but if the user click on a column header before starting of cell editing then the grid will be sorted and only the first 20 rows of result will be displayed. If you want to use local paging you have to include rowNum option with some large enough value, like rowNum: 10000.
It is strictly recommended to use gridview: true option to improve performance of grids and to use autoencode: true option to interpret the input data as pure data and not like HTML fragments. It will protect you from strange errors.
If colModel which you posted is full then the option sortname: 'value1' is wrong because the input data don't contains value1 property.

Changing the column position of rownumber property in JQgrid

I have enabled 'rownumber' property. So it is displaying row numbers by inserting a row in left most . So first column is displaying row numbers. ButI want to display row numbers in between i.e. in 3rd column.
Is there is any way to change column position?
Some columns of jqGrid have special meaning and will be created by jqGrid depend of the options which you use. It's "rn" (rownumbers: true), "cb" (multiselect: true) and subgrid (subGrid: true). See for example the line of code. Many parts of jqGrid code just test the options and then uses the indexes of columns based on the assumption that the columns are the first columns in jqGrid. So it's probably theoretically possible to write the code which could move the original "rn" column to another position, but the code will be very tricky and probably long. Look at the demo of the answer for example.
So I would recommend you just add your custom column to the grid which looks like "rn" column and fill it with the corresponding data. The column definition could be like below
{ name: "myRowNumbern", width:25, sortable: false, resizable: false, hidedlg: true,
search: false, align: "center", fixed: true,
classes: "ui-state-default jqgrid-rownum" }
UPDATED: I created the demo which demonstrates the approach. The most important parts of the corresponding code is below:
$("#list").jqGrid({
curRowNum: 1, // current row number parameter used in custom formatter
colModel: [
...
{ name: "myRowNumbern", width: 25, sortable: false, resizable: false,
hidedlg: true, search: false, align: "center", fixed: true,
classes: "ui-state-default jqgrid-rownum",
formatter: function () {
var p = $(this).jqGrid("getGridParam"),
rn = p.curRowNum +
(parseInt(p.page, 10) - 1)*parseInt(p.rowNum, 10);
p.curRowNum++;
return rn.toString();
} },
...
],
loadComplete: function () {
var p = $(this).jqGrid("getGridParam");
p.curRowNum = 1; // reset curRowNum
}
});

jqGrid filter toolbar show search operator selector just for single column

I have jqGrid table with many columns. Searching in grid is made using filter toolbar. For most of them search is just simple default operator. For one datetime column I want different kind of operators and datepicker selector.
I have added dataInit datepicker initialization to searchoptions, necessary operators to searchoptions.sopt. To show this operators I have set searchOperators to true. So for this column all is ok. I have datepicker with operator selector popup. But for all other columns default operator icon is shown on the left of it. It is annoying as operator is default and user couldn't change it. So is there is some possibility to hide them using jqGrid API? As far as I could see I could hide this only using my custom code:
I need to check my column model and after rendering of grid (may be in loadComplete) for all columns that have empty sopt or sopt.length == 0 to remove operator selector. Or add CSS class that hide it. Not sure which of these solution is better (hide or remove) because removing could broke some logic, and hiding could affect width calculation. Here is sample of what I mean on fiddle
function fixSearchOperators()
{
var columns = jQuery("#grid").jqGrid ('getGridParam', 'colModel');
var gridContainer = $("#grid").parents(".ui-jqgrid");
var filterToolbar = $("tr.ui-search-toolbar", gridContainer);
filterToolbar.find("th").each(function()
{
var index = $(this).index();
if(!(columns[index].searchoptions &&
columns[index].searchoptions.sopt &&
columns[index].searchoptions.sopt.length>1))
{
$(this).find(".ui-search-oper").hide();
}
});
}
Does anybody have some better ideas?
I find the idea to define visibility of searching operations in every column very good idea. +1 from me.
I would only suggest you to change a little the criteria for choosing which columns of searching toolbar will get the searching operations. It seems to me more native to include some new property inside of searchoptions. So that you can write something like
searchoptions: {
searchOperators: true,
sopt: ["gt", "eq"],
dataInit: function(elem) {
$(elem).datepicker();
}
}
I think that some columns, like the columns with stype: "select", could still need to have sopt (at least sopt: ["eq"]), but one don't want to see search operators for such columns. Specifying of visibility of searching operations on the column level would be very practical in such cases.
The modified fiddle demo you can find here. I included in the demo CSS from the fix (see the answer and the corresponding bug report). The full code is below
var dataArr = [
{id:1, name: 'steven', surname: "sanderson", startdate:'06/30/2013'},
{id:2, name: "valery", surname: "vitko", startdate: '07/27/2013'},
{id:3, name: "John", surname: "Smith", startdate: '12/30/2012'}];
function fixSearchOperators() {
var $grid = $("#grid"),
columns = $grid.jqGrid ('getGridParam', 'colModel'),
filterToolbar = $($grid[0].grid.hDiv).find("tr.ui-search-toolbar");
filterToolbar.find("th").each(function(index) {
var $searchOper = $(this).find(".ui-search-oper");
if (!(columns[index].searchoptions && columns[index].searchoptions.searchOperators)) {
$searchOper.hide();
}
});
}
$("#grid").jqGrid({
data: dataArr,
datatype: "local",
gridview: true,
height: 'auto',
hoverrows: false,
colModel: [
{ name: 'id', width: 60, sorttype: "int"},
{ name: 'name', width: 70},
{ name: 'surname', width: 100},
{ name: 'startdate', sorttype: "date", width: 90,
searchoptions: {
searchOperators: true,
sopt: ['gt', 'eq'],
dataInit: function(elem) {
$(elem).datepicker();
}
},
formatoptions: {
srcformat:'m/d/Y',
newformat:'m/d/Y'
}
}
]
});
$("#grid").jqGrid('filterToolbar', {
searchOnEnter: false,
ignoreCase: true,
searchOperators: true
});
fixSearchOperators();
It displays the same result like youth:

jqgrid inlinenav - custom row id and delete

Each row has an id in our db different to the jqgrid row id. How can I send this lineid when saving a row?
Also, is there a way to delete a row?
This is my code so far:
var mydata = [
{
lineItemId: "785",
productSku:"n123",
productName:"hello there",
pieces:"123",
value:"23.00",
line:"123"
}
,
{
lineItemId: "803",
productSku:"n1234",
productName:"hello there",
pieces:"123",
value:"23.00",
line:"123"
}
];
var colNames = ['SKU','Product Name', 'Pieces','Total Value','Line Number'];
var colModel = [
{name:'productSku', index:'productSku', width:10, sorttype: 'text', editable:true},
{name:'productName', index:'productName', width:60, editable:true},
{name:'pieces', index:'pieces', width:10, sorttype: 'int', editable:true, formatter: 'integer'},
{name:'value', index:'value', width:10, sorttype: 'int', editable:true, formatter: 'number'},
{name:'line', index:'line', width:10, sorttype: 'int', editable:true, formatter: 'integer', formatoptions:{thousandsSeparator: ""}}
];
initOrdersJqGrid("orderContent", mydata, '<xsl:value-of select="$datapath/OrderId"/>', colNames, colModel, "sku", "desc");
var orderLineOptions = {
keys: true,
aftersavefunc: function (rowid, response, options) {
// only update page if orderis is nil i.e. a new order
if($('#orderidlabel').text() == "") {
log('saving order line item from order with no id yet.');
var dummy = $('<div />').html(response.responseText);
var id = dummy.find('#orderId').val();
$('#orderidlabel').text(id);
$('#orderId').val(id);
$('button[value="Save Order"]').trigger('click');
}
}
}
function initOrdersJqGrid(id, data, orderid, colNames, colModel, defaultSortColumn, defaultSortOrder) {
$("#" + id + "Table")
.jqGrid({
datatype: "local",
data: data,
colNames: colNames,
colModel: colModel,
localReader: { id: "lineItemId"},
pager: '#' + id + 'Pager',
autowidth: true,
gridview: true,
autoencode: true,
height: "auto",
forceFit: true,
shrinkToFit: true, //Width of columns should be expressed in integers which add to 100
sortname: defaultSortColumn,
sortorder: defaultSortOrder,
url: "fs/servlet/CS",
editurl: "CS?action=com.agistix.webinterface.controllers.OrderIC,saveLineItems&orderId=" + orderid
})
.jqGrid('navGrid',"#" + id + "Pager",{edit:false,add:false,del:false,search: false, refresh: false})
.jqGrid('inlineNav',"#" + id + "Pager", { addParams: { addRowParams: orderLineOptions }, editParams: orderLineOptions});
}
If you use datatype: "local" then the items from the array of input data specified by data parameters should have additional property id which specify the value of id attribute of every row (<tr>) of the grid. If you prefer to have another name of the rowsid property you can use localReader to specify it. For example localReader: { id: "Id" } option inform jqGrid to get value of id attribute of rows (rowids) from the Id property. In the case the items of your data should bi like below
{
Id: 76453
productSku:"n123",
productName:"hello there",
pieces:"123",
value:"23.00",
line:"123"
}
The value of id property need be unique.
If you have already some column in the grid which contains id from some database table you don't need to add the same value with id property. Instead of that you can just key: true in the column. jqGrid allows to place key: true in only one item of colModel.
One more common problem with ids of rows it's important to understand. If you need to place more as one grid on a page or if you need to use Subgrid as Grid then you can still have one problem. The ids in database are unique in a table, but one can have the same ids in multiple tables. On the other side the ids of HTML elements (inclusive <tr> elements used for rows) must be unique over the whole page.
To solve the problem one can use idPrefix option of jqGrid. For example you have INT IDENTITY column in the database for the primary key of the table in the database. In the case you will have integers as native ids for rowids. The values can be for example 3, 5, 40 in the first grid. By usage idPrefix: "g1_" the ids assigned to the rows (to <tr> elements) will be "g1_3", "g1_5", "g1_40". So usage of idPrefix: "g1_" for the first grid and another value like idPrefix: "g2_" can solve the problem with potential id duplicates. It's important that jqGrid automatically strip the prefix idPrefix from rowid if it sends some data to the server (if you use editing in the grid for example). One can distinguish "id" and "rowid" names. The "rowids" will be always with prefix. You can use $.jgrid.stripPref function to cut the prefix.

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/

Resources