How to get the Jquery Autocomplete result event handler to work? - jquery-plugins

I wrote code that fails to use the JQuery autocomplete to fire a result function after the user selects something valid (below).
By result, I mean result handler, a function that fires after a good selection happens in the autocomplete plugin. Documented here.
In my case, I have a form that is really a table where each row is the same, minus the unique ids on the fields: Item1, Qty1, Desc1, then Item2, Qty2, Desc2, and so on. When the user types in an Item1 code, the Desc1 text should display the English of the item code selected (Item2 -> Desc2, and so on).
I used this code to find all the Item inputs and slap the autocomplete on it. The result event handler doesn't fire for some reason. If you notice, I hard coded the "Item1" selection because I haven't figured out how to select the corresponding Desc to the Item where Item1 -> Desc1, Item2 -> Desc2, and so on.
I used the MVC Url.Content only because I happen to get it working. Someone used Url.Action, which I think is better, just have to figure it out.
Feel free to correct my use as necessary, this is my first time with ASP.NET MVC / JQuery.
Thank you :)
The code:
$(document).ready(function(){
$("input[id^='Item']").autocomplete( "<%= Url.Content("~/products/autocomplete")%>", {
dataType: 'json',
parse: function(data) {
var rows = new Array();
for( var i = 0; i<data.length; i++)
{ rows[i] = {data:data[i], value:data[i].name, result:data[i].id }; }
return rows;
},
formatItem: function(row, i, n) {
return row.id + ' - ' + row.name;
},
selectFirst: true,
//autoFill: true,
minChars: 2,
max: 30,
autoFill: true,
mustMatch: true,
matchContains: false,
scrollHeight: 100,
width: 300,
cacheLength: 1,
scroll: true
});
$("Item1").result(function(event, data, formatted) {
$("Desc1").html( !data ? "No match!" : "Selected: " + formatted);
});
});

$(document).ready(function(){
$("input[id^='Item']").autocomplete( "<%= Url.Content("~/products/autocomplete")%>", {
dataType: 'json',
parse: function(data) {
var rows = new Array();
for( var i = 0; i<data.length; i++)
{ rows[i] = {data:data[i], value:data[i].name, result:data[i].id }; }
return rows;
},
formatItem: function(row, i, n) {
return row.id + ' - ' + row.name;
},
selectFirst: true,
//autoFill: true,
minChars: 2,
max: 30,
autoFill: true,
mustMatch: true,
matchContains: false,
scrollHeight: 100,
width: 300,
cacheLength: 1,
scroll: true
}).result(function(event, data, formatted) {
var n = $(this).attr("id").match(/\d+/);
var b = $("span[id='Desc"+n+"']")
b.html( !data ? "No match!" : "Selected: " + formatted);
});
});

Related

What causes jqgrid events to fire multiple times?

Our jqgrid is configured in an initgrid function that is called as the last statement of a ready handler. For some reason, the gridcomplete function is getting called multiple times. With the code below, it gets called twice, but it had been getting called 3 times. Twice is bad enough. After stepping through it multiple times, I don't see what is triggering the second execution of the gridComplete function.
When I hit the debugger at the start of gridComplete, the call stack is virtually identical each time, the only difference being a call to 'L' in the jqgrid:
Anyone have an idea why this is occurring? We are using the free version 4.13, in an ASP.net MVC application.
$(function(){
....
initGrid();
}
function initGrid(){
$gridEl.jqGrid({
xhrFields: {
cors: false
},
url: "/IAConsult/GetWorkFlowIARequests",
postData: {
showAll: showAllVal,
role: role,
IsIAArchitect: userIsIA
},
datatype: "json",
crossDomain: true,
loadonce: true,
mtype: 'GET',
sortable: true,
viewrecords: true,
pager: '#workFlowIAGridPager',
multiselect: true,
rowNum: 50,
autowidth: true,
colModel: [...],
beforeSelectRow: function (rowid, e) {
var $myGrid = $(this),
i = $.jgrid.getCellIndex($(e.target).closest('td')[0]),
cm = $myGrid.jqGrid('getGridParam', 'colModel');
return (cm[i].name === 'cb');
},
jsonReader: {
repeatitems: true,
root: "IAConsultWorkflowRequestsList"
},
beforeSubmitCell: function (rowid, name, value, iRow, iCol) {
return {
gridData: gridData
};
},
serializeCellData: function (postdata) {
return JSON.stringify(postdata);
},
gridComplete: function () {
console.log('grid complete');
let rowIDs = $gridEl.getDataIDs();
let inCompleteFlag = false;
let dataToFilter = $gridEl.jqGrid('getGridParam', 'lastSelectedData').length == 0
? $gridEl.jqGrid("getGridParam", "data")
: $gridEl.jqGrid('getGridParam', 'lastSelectedData');
let $grid = $gridEl, postfilt = "";
let localFilter = $gridEl.jqGrid('getGridParam', 'postData').filters;
let columnNames = columns.split(',');
$('.moreItems').on('click', function () {
$.modalAlert({
body: $(this).data('allitems'),
buttons: {
dismiss: {
caption: 'Close'
}
},
title: 'Design Participants'
});
});
rowCount = $gridEl.getGridParam('records');
gridViewRowCount = rowCount;
let getUniqueNames = function (columnName) {
... };
let buildSearchSelect = function (uniqueNames) {
var values = {};
values[''] = 'All';
$.each(uniqueNames,
function () {
values[this] = this;
});
return values;
};
let setSearchSelect = function (columnName) {
...
};
function getSortOptionsByColName(colName) {
...
}
$grid.jqGrid("filterToolbar",
{ stringResult: true, searchOnEnter: true });
if (localFilter !== "" && localFilter != undefined) {
globalFilter = localFilter;
}
let grid = $gridEl.jqGrid("setGridParam",
{
postData: {
"filters": globalFilter,
showAll: showAllVal,
role: role,
IsIAArchitect: userIsIA
},
search: true,
forceClientSorting: true
});
//grid.trigger("reloadGrid");
//Ending Filter code
for (i = 0; i < columnNames.length; i++) {
var htmlForSelect = '<option value="">All</option>';
var un = getUniqueNames(columnNames[i]);
var $select = $("select[id='gs_workFlowIAGrid_" + columnNames[i] + "']");
for (j = 0; j < un.length; j++) {
val = un[j];
htmlForSelect += '<option value="' + val + '">' + val + '</option>';
}
$select.find('option').remove().end().append(htmlForSelect);
}
debugger;
},
// all grid parameters and additionally the following
loadComplete: function () {
$gridEl.jqGrid('setGridWidth', $(window).width(), true);
$gridEl.setGridWidth(window.innerWidth - 20);
},
height: '100%'
});
I personally almost never use gridComplete callback. It exists in free jqGrid mostly for backwards compatibility. I'd recommend you to read the old answer, which describes differences between gridComplete and loadComplete.
Some additional advices: it's dangerous to register events inside of callbacks (see $('.moreItems').on('click', ...). If you need to make some actions on click inside of grid then I'd recommend you to use beforeSelectRow. Many events, inclusive click event supports event bubbling and non-handled click inside of grid will be bubbled to the parent <table> element. You use already beforeSelectRow callback and e.target gives you full information about clicked element.
I recommend you additionally don't use setGridParam method, which can decrease performance. setGridParam method make by default deep copy of all internals parameters, inclusive arrays like data, which can be large. In the way, changing one small parameter with respect of setGridParam can be expensive. If you need to modify a parameter of jqGrid then you can use getGridParam without additional parameters to get reference to internal object, which contains all jqGrid parameters. After that you can access to read or modify parameters of jqGrid using the parameter object. See the answer for example for small code example.
Also adding the property
loadonce: true
might help.

scroll to jqgrid item by id/key

I've a jqgrid width multiple pages. Every row has an unique id. Is there a function to scroll directly i.e. to row id 1234?
var mygrid = $("#list").jqGrid({
url: 'get_sql_json.php',
datatype: "json",
mtype: "GET",
pager: "#pager",
rowNum: 100,
rowList: [100, 200, 500],
autoencode: true,
autowidth: true,
sortorder: "desc",
shrinkToFit: true,
viewrecords: true,
loadonce: true,
gridview: true,
autoencode: true
});
I find your question very interesting, so I prepared the demo which demonstrates the corresponding solution.
One can choose the row in the dropdown-box and click the button "Select row by id". The specified row will be selected with setSelection method if it is on the current page. If the row in on another page then it will be calculated new page number and the grid will be reloaded with the specified row pre-selected. I use current: true option of reloadGrid described here.
It's important that you use loadonce: true which allows to save more as one page of rows. In the case the grid works like the grid having datatype: "local" with data parameter defined with the data returned from the server at the first load.
For the implementation of the selection I use the approach described in the answer. I overwrite (subclass) the select method of internal $.jgrid.from method used by jqGrid so that the last full sorted and filtered local data are saved in new internal variable lastSelected. It allows to access the full dataset instead of the current page only (the contains the data from the line instead of the current page only after execution of slice from the line).
The most important part of the code of the demo is below:
var mydata = [ ... ],
$grid = $("#list"),
oldFrom = $.jgrid.from,
lastSelected, i, n, $ids, id;
// "subclass" $.jgrid.from method and save the last
// select results in lastSelected variable
$.jgrid.from = function (source, initalQuery) {
var result = oldFrom.call(this, source, initalQuery),
old_select = result.select;
result.select = function (f) {
lastSelected = old_select.call(this, f);
return lastSelected;
};
return result;
};
// create the grid
$grid.jqGrid({
datatype: "local",
data: mydata,
...
loadComplete: function () {
this.p.lastSelected = lastSelected; // set this.p.lastSelected
}
});
...
// fill select with all ids from the data
$ids = $("#selectedId");
for (i = 0, n = mydata.length; i < n; i++) {
id = mydata[i].id;
$("<option>").val(id).text(id).appendTo($ids);
}
$("#selectId").button().click(function () {
var filteredData = $grid.jqGrid("getGridParam", "lastSelected"), j, l,
idName = $grid.jqGrid("getGridParam", "localReader").id,
idToSelect = $("#selectedId").val(),
rows = $grid.jqGrid("getGridParam", "rowNum"),
currentPage = $grid.jqGrid("getGridParam", "page"),
newPage;
if (filteredData) {
for (j = 0, l = filteredData.length; j < l; j++) {
if (String(filteredData[j][idName]) === idToSelect) {
// j is the 0-based index of the item
newPage = Math.floor(j / rows) + 1;
if (newPage === currentPage) {
$grid.jqGrid("setSelection", idToSelect);
} else {
// set selrow or selarrrow
if ($grid.jqGrid("getGridParam", "multiselect")) {
$grid.jqGrid("setGridParam", {
page: newPage,
selrow: idToSelect,
selarrrow: [idToSelect]
});
} else {
$grid.jqGrid("setGridParam", {
page: newPage,
selrow: idToSelect
});
}
$grid.trigger("reloadGrid", [{current: true}]);
break;
}
}
}
if (j >= l) {
$grid.jqGrid("resetSelection");
alert("The id=" + idToSelect + " can't be seen beacuse of the current filter.");
}
}
});
You can select an ID using setSelection to scroll to that row, but only if it is on the current page.

google maps and ajax

Is it possible to return a variable, more specifically an array of values or a string from an $.ajax call. I currently understand that this can't be done... i.e. $.ajax responses need to be added to the DOM immediately. Please correct me if I am missing something obvious here.
var infoWindow;
var tableID = 'atableID';
var str;
var beachID;
var beach_location;
var beach_region;
/* start map initialization */
function initialize() {
latlng = new google.maps.LatLng(49.894634, -97.119141);
var myOptions = {
center: latlng,
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
mapTypeControl: true,
mapTypeControlOptions: {
mapTypeIds: [
google.maps.MapTypeId.ROADMAP,
google.maps.MapTypeId.SATELLITE,
google.maps.MapTypeId.HYBRID,
google.maps.MapTypeId.TERRAIN
],
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
overviewMapControl: true,
overviewMapControlOptions: {
opened: true
}
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
layer = new google.maps.FusionTablesLayer({
query: {
select: 'Point',
from: atableID
},
suppressInfoWindows: true
});
layer.setMap(map);
infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(layer, 'click', function (e) {
// close infoWindow if open
if (infoWindow) {
infoWindow.close();
}
beachID = e.row['Beach_ID'].value;
beach_location = e.row['Beach_Location'].value; ;
beach_region = e.row['Beach_Region'].value;;
//console.log(beachID);
// get data set
getEcoliData(beachID,beach_location,beach_region);
getAlgaeData(beachID,beach_location,beach_region);
}); // end google.maps.addListener
} // end map initialization
function getEcoliData(beachID,beach_location,beach_region) {
//local namespace
var rows = [];
var ecoliTable;
var items = [];
var queryURL = "https://www.googleapis.com/fusiontables/v1/query?sql=";
var queryTail = '&key=a key value=?';
var whereClause = "WHERE 'Beach_ID' = " + beachID;
var query = "SELECT 'Sample_Date', 'Average_E._coli_Density','Recreational_Water_Quality_Guideline' FROM atblid " + whereClause + " ORDER BY 'Sample_Date' DESC";
var queryText = encodeURI(query);
$.ajax({
type: "GET",
url: queryURL + queryText + queryTail,
cache: false,
dataType: 'jsonp',
success: function (data) {
rows = data.rows;
// empty table
//$('#content_placeholder').empty();
//$('.ecoli_table').remove();
$('#ecoli_heading').empty();
$('#content_placeholder').prepend('<h6 id="ecoli_heading">E.Coli Data</h6>')
.append('<p>' + beach_location + '</p>').append('<p>' + beach_region + '</p>');
$('.ecoli_table').append('<tr>'
+ '<th>Sample Date</th>'
+ '<th>Average E.Coli Density</th>'
+ '<th>Recreational Water Quality Guideline</th>'
+ '</tr>');
for (var i = 0; i < rows.length; i++) {
//items.push(rows[i]);
$('.ecoli_table tr:first').after('<tr><td>' + rows[i].join('</td><td>') + '</td></tr>');
}
if (typeof ecoliTable == 'undefined') {
// dataTables
ecoliTable = $(".ecoli_table").dataTable({
"sPaginationType": "full_numbers",
"aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
"aaSorting": [[0, "desc"]],
"bDestroy": true,
"aoColumns": [
{ "sTitle": "Sample_Date" },
{ "sTitle": "Average_E._coli_Density" },
{ "sTitle": "Recreational_Water_Quality_Guideline" }
]
});
} else {
//ecoliTable.fnDestroy();
$(".ecoli_table > tbody").empty();
ecoliTable.fnDraw();
//$('.ecoli_table').find("tr:gt(0)").remove();
}
},
error: function () {
alert("Data is not available for this location at the present time, please check back at a later time. Thank you.");
}
});
}
function getAlgaeData(beachID,beach_location,beach,region) {
//local namespace
var rows = [];
var algaeTable;
var items = [];
var queryURL = "https://www.googleapis.com/fusiontables/v1/query?sql=";
var queryTail = '&key=apikey&callback=?';
var whereClause = "WHERE 'Beach_ID' = " + beachID;
var query = "SELECT 'Sample_Date','Algal_Toxin_Microcystin','Recreational_Guideline_20','Blue_Green_Algae_Cells','Recreational_Guideline' FROM tableid " + whereClause + " ORDER BY 'Sample_Date' DESC";
var queryText = encodeURI(query);
$.ajax({
type: "GET",
url: queryURL + queryText + queryTail,
cache: false,
dataType: 'jsonp',
success: function (data) {
rows = data.rows;
// empty table
//$('#content_placeholder').empty();
//$('.algae_table').remove();
$('#algae_heading').empty();
$('.ecoli_table').after('<h6 id="algae_heading">Algae Data</h6>');
$('.algae_table').append('<tr>'
+ '<th>Sample Date</th>'
+ '<th>Algal_Toxin_Microcystin</th>'
+ '<th>Recreational_Guideline_20</th>'
+ '<th>Blue_Green_Algae_Cells</th>'
+ '<th>Recreational_Guideline</th>'
+ '</tr>');
for (var i = 0; i < rows.length; i++) {
//items.push(rows[i]);
$('.algae_table tr:first').after('<tr><td>' + rows[i].join('</td><td>') + '</td></tr>');
}
if (typeof algaeTable == 'undefined') {
//algae
algaeTable = $(".algae_table").dataTable({
"sPaginationType": "full_numbers",
"aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
"bDestroy": true,
"aaSorting": [[0, "desc"]],
"aoColumns": [
{ "sTitle": "Sample_Date" },
{ "sTitle": "Algal_Toxin_Microcystin" },
{ "sTitle": "Recreational_Guideline_20" },
{ "sTitle": "Blue_Green_Algae_Cells" },
{ "sTitle": "Recreational_Guideline" }
]
});
} else {
//algaeTable.fnDestroy();
$(".algae_table > tbody").empty();
algaeTable.fnDraw();
//$('.algae_table').find("tr:gt(0)").remove();
}
},
error: function () {
alert("Data is not available for this location at the present time, please check back at a later time. Thank you.");
}
});
}
I am trying to query 2 different Google Fusion tables and return each table under a new tab within a google infoWindow. However, I am running into issues because I can't seem to return an array or string from the $.ajax function to the parent scope. For example, the items array above returns undefined. Any thoughts around this is greatly appreciated.
Thanks in advance,
Michael
It is definitely possible. You haven't provided enough code to determine what's wrong, e.g. queryURL, queryText, etc. You'll need your Google API key as well. Here is an example demonstrating how to do it.
https://developers.google.com/fusiontables/docs/samples/basic_jsonp_request

jqGrid change dynamically edittype for specific row

Following to this post where I found some way to do that I would want to get, I meet some trouble with it.
Here is my code :
var myDlg = $("#dlgpers"),lastsel;
myDlg.jqGrid({
url:'pers.php?id='+dataRow.id,
mtype:'GET',
datatype: "json",
ajaxGridOptions: { cache: false },
height:250,
cmTemplate: {sortable:false},
gridview: true,
cellEdit:true,
scroll:false,
colNames:['Id','Label','Information','Type','Data'],
colModel:[
{name:'id',index:'id',hidden:true,key:true},
{name:'label',index:'label',align:'right',width:100,editable:false,
cellattr: function (rowId, val, rawObject, cm, rdata) {
return ' style="font-weight:bold;margin-right:5px;border-left:0;border-top:0;" class="ui-state-active"' ;
}
},
{name:'info',index:'info',width:200,editable:true,edittype:'text'},
{name:'type',index:'type',width:30,hidden:true},
{name:'data',index:'data',width:30,hidden:true}
],
loadComplete: function () {
var rowIds = myDlg.jqGrid('getDataIDs');
$.each(rowIds, function (i, row) {
var rowData = myDlg.jqGrid('getRowData',row);
if (rowData.type == 'select') {
myDlg.jqGrid('restoreRow', row);
var cm = myDlg.jqGrid('getColProp', 'info');
cm.edittype = 'select';
cm.editoptions = { value: rowData.data };
myDlg.jqGrid('editRow', row);
cm.edittype = 'text';
cm.editoptions = null;
cm.editable = true;
}else{
myDlg.jqGrid('restoreRow', row);
var cm = myDlg.jqGrid('getColProp', 'info');
cm.edittype = 'text';
cm.editoptions = null;
cm.editable = true;
myDlg.jqGrid('editRow', row);
cm.edittype = 'text';
cm.editoptions = null;
cm.editable = true;
}
});
}
});
and the result as image :
and the JSON response :
{"page":1,"total":1,"records":1,"rows":[
{"cell":[0,"Nom ","LEBRUN","text",""]},
{"cell":[1,"Pr\u00e9nom ","Jacques","text",""]},
{"cell":[2,"Initiales ","LJ","text",""]},
{"cell":[3,"Fonction ","","text",""]},
{"cell"[4,"Service,"Administratif","select","0:Administratif;1:Commercial;2:Magasin;3:M\u00e9canique;4:Rejointage;5:Soudure;6:Tests"]},
{"cell":[5,"T\u00e9l\u00e9phone ","","text",""]},
{"cell":[6,"Email ","","text",""]},
{"cell":[7,"Statut ","CDI","select","0:CDI;1:CDD;2:App;3:Stg;4:Int"]},
{"cell":[8,"Entr\u00e9 le ","2008-10-06","text",""]},
{"cell":[9,"Sorti le ","0000-00-00","text",""]}]}
Two questions I submit to your knowledge:
As you can see, the second line (Prénom) don't seem editable, but it is.
I don't understand why these inputs are visible, as I would want they appear only if I edit some cell.
Many thanks for all your kind help for resolve (and explain) my wrong way.
JiheL
UPDATED 2013-03-29
I have applied your answer code and that run fine ! Many thanks.
But I have created another form in such a way for another subject, and that cause me some troubles.
Here is the code of this new form :
var showAbs=function(){
$('#EditDialog').empty();
var $table=$('<table></table>')
.attr('id','dlgcong')
.appendTo($('#EditDialog'));
var myCong = $("#dlgcong");
myCong.jqGrid({
url:'xpabs.php?id='+id+'&y='+y,
datatype: "json",
height:"auto",
cmTemplate: {sortable:false},
gridview: true,
colNames:['Type absence','Début','Fin','id'],
colModel:[
{name:'abs',index:'abs',width:155,editable:true,edittype:'select',
editoptions:{
dataUrl:"selabs.php",
dataEvents: [
{
type: 'change',
fn: function(e) {
$(this).parent().css('background-color','#'+$(this).find('option:selected').attr('colr'));
if($(this).find('option:selected').attr('colr')=='ffffff'){
$(this).parent().parent().find('input').datepicker('disable');
}else{
$(this).parent().parent().find('input').datepicker('enable');
$(this).parent().parent().attr('changed',true);
}
}
}
]
},
cellattr: function (rowId, val, rawObject, cm, rdata) {
return ' style="background-color:#'+rawObject[4]+';color:white;"';
}
},
{name:'debut',index:'debut',align:'center',width:70,editable:true},
{name:'fin',index:'fin',align:'center',width:70,editable:true},
{name:'id',index:'id',hidden:true}
],
jsonReader: {
cell: "",
root: function (obj) {
return obj;
}
},
loadComplete: function (data) {
var $self = $(this),
cm = $self.jqGrid("getColProp", "debut"),
idPrefix = $self.jqGrid("getGridParam", "idPrefix"),
l = data.length,
i,
item;
for (i = 0; i < l; i++) {
item = data[i];
cm.editoptions = {
dataInit: function(element) {
$(element).datepicker({
setDate:item[1],
minDate:'01/01/'+y,
maxDate:'31/12/'+y,
onSelect: function( selectedDate,inst ) {
$(element).val(selectedDate );
$(element).parent().parent().attr('changed',true);
}
})
}
}
}
var cm = $self.jqGrid("getColProp", "fin");
for (i = 0; i < l; i++) {
item = data[i];
cm.editoptions = {
dataInit: function(element) {
$(element).datepicker({
setDate:item[2],
minDate:'01/01/'+y,
maxDate:'31/12/'+y,
onSelect: function( selectedDate,inst ) {
$(element).val(selectedDate );
$(element).parent().parent().attr('changed',true);
}
})
}
}
$self.jqGrid("editRow", idPrefix + item[3]);
}
myCong.find('select').each(function(){
$(this).css({
backgroundColor:'transparent',
color:'white',
border:0,
width:155
});
});
},
idPrefix: "cong",
rowNum: 10000
});
//********************
// Button ' Valider '
//********************
$('<input />')
.attr({
type:'button',
})
.css({
float:'right',
marginTop:'5px'
})
.click(function(){
var toBeSaved='';
myCong.find('tr[changed=true]').each(function(idx){
if(toBeSaved.length>0){
toBeSaved+='|';
}
toBeSaved+=$(this).find('td:eq(3)').text()+';';
toBeSaved+=$(this).find('select option:selected').val()+';';
toBeSaved+=$(this).find('input:eq(0)').val()+';';
toBeSaved+=$(this).find('input:eq(1)').val();
});
if(toBeSaved.length>0){
$.ajax({
url:'majpabs.php?id='+id+'&data='+toBeSaved,
async:false,
dataType:'json',
success:function(data){
myGrid.trigger('reloadGrid');
$('#newAbs').val(' Nouveau ').attr('disabled',false);
}
});
}
})
.val(' Valider les absences ')
.appendTo($('#EditDialog'));
//*******************
// Button ' Retour '
//*******************
$('<input />')
.attr({
type:'button',
id:'newAbs'
})
.css({
float:'left',
marginTop:'5px'
})
.click(function(){
showPers();
})
.val(' Retour ')
.appendTo($('#EditDialog'));
//********************
// Button ' Nouveau '
//********************
$('<input />')
.attr({
type:'button',
disabled:false
})
.css({
float:'left',
marginTop:'5px',
marginLeft:'7px'
})
.click(function(){
if($(this).val()==' Nouveau '){
var myRow = {abs:"0", debut:'00/00/'+y, fin:'00/00/'+y, id:'0'};
myCong.jqGrid('addRowData','',myRow, 'last');
$(this).val(' Sauver ').attr('disabled',true);
}else{
}
})
.val(' Nouveau ')
.appendTo($('#EditDialog'));
}
and the result as image :
As you can see, the first row does not receive select and datepicker as other rows. Strange !
When I add new row, it does not receive select and datepicker as the first row.
I think I'm wrong in understanding this method.
I'm worry to bother you with these questions, I had a look in wiki without success to find any way to make these points correct. I would like to find some more detailed tutorial which show some cases examples.
Thank you VERY MUCH if you can spend again some time for give me a way to be more efficient with jqGrid.JiheL
UPDATED 2013-04-01
I have applied Oleg's suggestions and that works now. But a trouble remains.
here is the image :
For the first row, select box is OK.
The first input field receive datepicker, but the second (the column called 'fin') not !
All others rows receive well datepickers, but not the last field of first row.
Here is the code :
loadComplete: function (data) {
var $self = $(this),
idPrefix = $self.jqGrid("getGridParam", "idPrefix"),
l = data.length,
i,
item,
cm;
for (i = 0; i < l; i++) {
item = data[i];
cm = $self.jqGrid("getColProp", "debut");
cm.editoptions = {
dataInit: function(element) {
//alert('deb'+i);
$(element).datepicker({
setDate:item[1],
minDate:'01/01/'+y,
maxDate:'31/12/'+y,
onSelect: function( selectedDate,inst ) {
$(element).val(selectedDate );
$(element).parent().parent().attr('changed',true);
}
})
}
};
$self.jqGrid("editRow", idPrefix + item[3]);
//
cm = $self.jqGrid("getColProp", "fin");
cm.editoptions = {
dataInit: function(element) {
//alert('fin'+i);
$(element).datepicker({
setDate:item[2],
minDate:'01/01/'+y,
maxDate:'31/12/'+y,
onSelect: function( selectedDate,inst ) {
$(element).val(selectedDate );
$(element).parent().parent().attr('changed',true);
}
})
}
};
$self.jqGrid("editRow", idPrefix + item[3]);
}
myCong.find('select').each(function(){
$(this).css({
backgroundColor:'transparent',
color:'white',
border:0,
width:155
});
});
},
Another time, I hope you can help me to resolve this trouble and close this request.
Many thanks for all the time you spend to help newbies.
JiheL
I think that many from the problems in your code common. So I tried to answer on you question more detailed.
First of all you posted wrong JSON data. The line
{"cell"[4,"Service,"Administratif","select","0:Administratif;1:Commercial;2:Magasin;3:M\u00e9canique;4:Rejointage;5:Soudure;6:Tests"]},
contains two errors:
no ':' after "cell"
no " after "Service
After the changes the line will be so
{"cell":[4,"Service","Administratif","select","0:Administratif;1:Commercial;2:Magasin;3:M\u00e9canique;4:Rejointage;5:Soudure;6:Tests"]},
and JSON data could be read. The next problem is the usage of numbers together with string in one array. Because the bug in the line of jqGrid code
idr = ccur !== undefined ? ccur[idn] || idr : idr;
ids could not be integer value 0. I posted the bug report about the error. To fix the problem using existing code of jqGrid you should use strings instead of numbers. For example the line
{"cell":[0,"Nom ","LEBRUN","text",""]},
should be changed to
{"cell":["0","Nom ","LEBRUN","text",""]},
Without the changes you will have id duplicates. Both first lines ({"cell":[0,"Nom ","LEBRUN","text",""]} and {"cell":[1,"Pr\u00e9nom ","Jacques","text",""]},) will get the same id equal to 1 instead of 0 and 1. It was the main reason of the problem which you described.
Additionally I would recommend you the following:
remove cellEdit:true option. You use editRow later in the code. It means that you use inline editing instead of cell editing which means cellEdit:true. You can't combine both editing modes in one grid.
replace height:250 option to height:"auto"
remove all index properties from colModel. Remove all properties of colModel with default values (edittype:'text', editable:false)
remove options of jqGrid with default values (mtype:'GET', scroll:false)
all parameters of functions in JavaScript are optional. So if you don't use for example any parameters of cellattr callback you can replace cellattr: function (rowId, val, rawObject, cm, rdata) {...} to cellattr: function () {...}
the callback loadComplete has one parameter data which can provide you all data which returned from the server. So you don't need to use getDataIDs and getRowData. The array data.rows can by directly used.
if you use data parameter of loadComplete callback you can remove unneeded 'type' and 'data' columns from the grid.
if you place information about id after 'Label','Information' then you can use id property of jsonReader and remove hidden id column from the grid too. For example if you move id as the last in the cell array you can use jsonReader: {id: 4} and remove hidden id column from the grid. If you add additionally cell: "" property in jsonReader you can remove "cell": from the input data. If you would use root property of jsonReader defined as function (see the documentation) you can remove some unneeded data from the server response.
For example the server can produce the simplified data
[
["Nom ","LEBRUN","text","","0"],
["Pr\u00e9nom ","Jacques","text","","1"],
["Initiales ","LJ","text","","2"],
["Fonction ","","text","","3"],
["Service","Administratif","select","0:Administratif;1:Commercial;2:Magasin;3:M\u00e9canique;4:Rejointage;5:Soudure;6:Tests","4"],
["T\u00e9l\u00e9phone ","","text","","5"],
["Email ","","text","","6"],
["Statut ","CDI","select","0:CDI;1:CDD;2:App;3:Stg;4:Int","7"],
["Entr\u00e9 le ","2008-10-06","text","","8"],
["Sorti le ","0000-00-00","text","","9"]
]
The corresponding jqGrid could be
$("#dlgpers").jqGrid({
url: "pers.php?id=" + dataRow.id,
datatype: "json",
height: "auto",
cmTemplate: {sortable: false},
gridview: true,
colNames: ["Label", "Information"],
colModel: [
{name: "label", align: "right", width: 100,
cellattr: function () {
return ' style="font-weight:bold;margin-right:5px;border-left:0;border-top:0;" class="ui-state-active"';
}},
{name: "info", width: 200, editable: true}
],
jsonReader: {id: 4, cell: "", root: function (obj) { return obj; } },
loadComplete: function (data) {
var $self = $(this),
cm = $self.jqGrid("getColProp", "info"),
idPrefix = $self.jqGrid("getGridParam", "idPrefix"),
l = data.length,
i,
item;
for (i = 0; i < l; i++) {
item = data[i];
cm.edittype = item[2] === "select" ? "select" : "text";
cm.editoptions = { value: item[3] };
$self.jqGrid("editRow", idPrefix + item[4]);
}
},
idPrefix: "dlg",
rowNum: 10000 // to have no paging
});
See the demo:

jqgrid Subgrid as a Grid: Edit, Add, Search Icons not appearing in Subgrid

This is the code for my Grid. But for some reason the edit, add, and search icons are not displaying in subgrid:
$(document).ready(function(){
var gridwidth = $('.tableContainer').width();
gridwidth = gridwidth-40;
var myGrid = jQuery("#list");
editSettings = {
recreateForm:true,
reloadAfterSubmit:false,
closeOnEscape:true,
closeAfterEdit:true,
width:"1250"
},
addSettings = {
recreateForm:true,
reloadAfterSubmit:false,
closeOnEscape:true,
closeAfterAdd:true
};
myGrid.jqGrid(
{
url:'projects.cfc?method=getProjects&returnformat=json&_cf_nodebug=true', //CFC that will return the projects
datatype: 'json', //We specify that the datatype we will be using will be JSON
complete: function(jsondata, stat) {
if (stat == "success") {
myGrid = jQuery("#list")[0];
myGrid.addJSONData(JSON.parse(jsondata.responseText).d);
} else {
alert('Error processing JSON');
}
},
colNames:[ .....],
colModel :[{ ...}], //it the operators available during search
pager: $('#pager'), //The div we have specified, tells jqGrid where to put the pager
rowNum: 150, //Number of records we want to show per page
rowList:[20,30,40,50,75,150], //Row List, to allow Initiative to select how many rows they want to see per page
sortorder: "asc", //Default sort order
sortname: "PROJECTS.PROJECTID", //Default sort column
viewrecords: true, //Shows the nice message on the pager
imgpath: '/images', //Image path for prev/next etc images
caption: 'Initiatives', //Grid Name
recordtext: "Record {0} - {1} of {2}",//Pager information to show
rownumbers: false,//Do not show row numbers
sortable: true,
width:'auto',
height:'auto', //I like auto, so there is no blank space between. Using a fixed height can mean either a scrollbar or a blank space before the pager
mtype:'POST',
toolbar:[true,"bottom"], //Shows the toolbar at the top. We will use it to display Initiative feedback
subGrid: true,
subGridRowExpanded: function(subgrid_id, row_id) {
// we pass two parameters
// subgrid_id is a id of the div tag created within a table
// the row_id is the id of the row
// If we want to pass additional parameters to the url we can use
// the method getRowData(row_id) - which returns associative array in type name-value
// here we can easy construct the following
var subgrid_table_id, pager_id;
subgrid_table_id = subgrid_id+"_t";
pager_id = "p_" + subgrid_table_id;
jQuery("#"+subgrid_id).html("<table id='"+subgrid_table_id+"' cellpadding='0' cellspacing='0' class='scroll'></table><div id=’" + pager_id + "’ class=’scroll’></div>");
jQuery("#"+subgrid_table_id).jqGrid({
url:"projects.cfc?method=getProjectMilestones&projectid="+row_id,
datatype: "json",
colNames:['SEQ','ID','MILESTONE','TREND','DUE DATE','STATUS','OWNERS','%','COMMENTS'], //Column Names
//The Column Model to define the data. Note you can make columns non sortable, specify width, alignment, etc.
colModel :[
{name:'SEQUENCENUM',index:'SEQUENCENUM',hidden:true},
{name:'PROJECTID',index:'PROJECTID', editable:false},
{name:'MILESTONE',index:'MILESTONE', width:150, sorttype:"text",align:"center",
editable:true,edittype:"text",
editrules:{required:true}},
{name:'TREND',index:'TREND', width:100, align:"center",sorttype:"text",
editable:true,edittype:"select",editoptions:{value:"Green:Green;Yellow:Yellow;Red:Red"},
editrules:{required:true}},
{name:'DUE_DATE',index:'DUE_DATE', width:150, editable:true,editoptions:{size:12,dataInit: function(el) {
$(el).datepicker({ dateFormat: 'mm-dd-yy'} );
},
defaultValue: function() {
var currentTime = new Date();
var month = parseInt(currentTime.getMonth() + 1);
month = month <= 9 ? "0" + month : month;
var day = currentTime.getDate();
day = day <= 9 ? "0" + day : day;
var year = currentTime.getFullYear();
return month + "-" + day + "-" + year ;
}
},align:"center",
editrules:{required:true}},
{name:'MILESTONE_STATUS',index:'MILESTONE_STATUS',
editable:true,edittype:"select",editoptions:{value:"In Progress:In Progress;Complete:Complete"},
editrules:{required:true}},
{name:'ASSIGNMENT',index:'ASSIGNMENT', width:125,align:"center",sorttype:"text",
editable:true,edittype:"text",
editrules:{required:true}},
{name:'PERCENT_COMP',index:'PERCENT_COMP', width:50, sorttype:"int",align:"center",
editable:true,edittype:"text",editrules:{number:true}},
{name:'COMMENTS',index:'COMMENTS', width:200,
editable:true,edittype:"textarea",editoptions:{rows:3, cols:30},
editrules:{required:true}}
],//searchoptions parameter is used to limit the operators available during search,
rowNum: 20, //Number of records we want to show per page
rowList:[20,30,40,50], //Row List, to allow Initiative to select how many rows they want to see per page
sortorder: "asc", //Default sort order
sortname: "SEQUENCENUM", //Default sort column
viewrecords: true, //Shows the nice message on the pager
imgpath: 'images/', //Image path for prev/next etc images
caption: 'Milestones', //Grid Name
recordtext: "Record {0} - {1} of {2}",//Pager information to show
rownumbers: false,//Do not show row numbers
sortable: true,
width:'auto',
height:'auto', //I like auto, so there is no blank space between. Using a fixed height can mean either a scrollbar or a blank space before the pager
mtype:'POST',
toolbar:[true,"bottom"], //Shows the toolbar at the top. We will use it to display Initiative feedback
shrinkToFit: true,
//The JSON reader. This defines what the JSON data returned from the CFC should look like
jsonReader: {
root: "ROWS", //our data
page: "PAGE", //current page
total: "TOTAL", //total pages
records:"RECORDS", //total records
userdata:"USERDATA",
cell: "", //Not Used
id: "0", //Will default to first column
subGrid: {
root : "ROWS",
repeatitems: true,
cell: "" //Not Used
}
},
editurl:'projects.cfc?method=addeditMilestone&projectid='+row_id, //The Add/Edit function call
pager:('#' + pager_id)
}).navGrid('#' + pager_id, {
search:false,//title set for hover over display
edit:true,edittitle:"Edit Milestone",width:200,
add:true,addtitle:"Add Milestone",width:200,
del:true,deltitle:"Delete Milestone"
},
// Edit Options. save key parameter will keybind the Enter key to submit.
{editCaption:"Edit Milestone",edittext:"Edit",closeOnEscape:true,closeAfterEdit:true,savekey: [true,13],errorTextFormat:commonError,width:"500"
,reloadAfterSubmit:true,bottominfo:"Fields marked with (*) are required",top:"60",left:"5",right:"5"},
{addCaption:"Add Milestone",closeOnEscape:true,closeAfterAdd:true,savekey: [true,13],errorTextFormat:commonError,width:"500"
,reloadAfterSubmit:true,bottominfo:"Fields marked with (*) are required",top:"60",left:"5",right:"5"},
//Add Options
{url:"projects.cfc?method=delMilestone",caption:"Delete Milestone",closeOnEscape:true,errorTextFormat:commonError,top:"60",left:"70",
reloadAfterSubmit:true} //Delete Options
)
},
shrinkToFit: true,
//The JSON reader. This defines what the JSON data returned from the CFC should look like
jsonReader: {
root: "ROWS", //our data
page: "PAGE", //current page
total: "TOTAL", //total pages
records:"RECORDS", //total records
userdata:"USERDATA",
cell: "", //Not Used
id: "0" //Will default to first
},
loadComplete: function() {
$('#cb').prev().remove();
if($("#list").getGridParam("RECORDS")==0){
$('#noResults').dialog("open");
} else {
var page = $('#list').getGridParam("PAGE");
var records = $('#list').getGridParam("RECORDS");
var recordsPP = $('#list').getGridParam("rowNum");
var x = records/recordsPP;
var returnArray = [];
if(x < page) {
iterLimit = records%recordsPP;
} else {
iterLimit = recordsPP;
}
for(var i=1; i<=iterLimit; i++) {
$('#'+i).children('td:first').next().addClass('link').css("cursor","pointer").css("color","blue").css("text-decoration","underline");
var emitid = $('#'+i).children ('td:first').next().text();
//window.alert(emitid);
$('#'+i).children('td:first').next().click(function() {
emitid = $(this).text();
//window.alert(emitid + ":" + page + ":" + records + ":" + recordsPP + ":" + x);
var link = 'viewInitiative.cfm?projectid='+emitid
window.open(link,'_blank');
});
//returnArray = orderList.find(ord);
var truefalse = typeof returnArray;
if(truefalse != 'boolean') {
$('#list').setSelection(i);
}
}
}
},
loadError:function(xhr, st, err) {
alert('loaderror on quote request grid - ' + st)
},
editurl:"projects.cfc?method=addeditProject", //The Add/Edit function call
ondblClickRow: function(rowid, ri, ci) {
var p = myGrid[0].p;
if (p.selrow !== rowid) {
// prevent the row from be unselected on double-click
// the implementation is for "multiselect:false" which we use,
// but one can easy modify the code for "multiselect:true"
myGrid.jqGrid('setSelection', rowid);
}
myGrid.jqGrid('editGridRow', rowid, editSettings);
}
}).navGrid('#pager',
{
search:true,searchtitle:"Search",//title set for hover over display
edit:true,edittitle:"Edit Initiative",width:1000,
add:true,addtitle:"Add Initiative",width:1000,
del:true,deltitle:"Delete Initiative"
},
// Edit Options. save key parameter will keybind the Enter key to submit.
{editCaption:"Edit Initiative",edittext:"Edit",closeOnEscape:true,closeAfterEdit:true,savekey: [true,13],errorTextFormat:commonError,width:"1250"
,reloadAfterSubmit:true,bottominfo:"Fields marked with (*) are required",top:"60",left:"5",right:"5"},
{addCaption:"Add Initiative",closeOnEscape:true,closeAfterAdd:true,savekey: [true,13],errorTextFormat:commonError,width:"1250"
,reloadAfterSubmit:true,bottominfo:"Fields marked with (*) are required",top:"60",left:"5",right:"5"},
//Add Options
{url:"projects.cfc?method=delProject",caption:"Delete Initiative",closeOnEscape:true,errorTextFormat:commonError,top:"60",left:"70",
reloadAfterSubmit:true}, //Delete Options
//Search Options. multipleSearch parameter lets it know we are going to use the new advanced search feature
{errorTextFormat:commonError,Find:"Search",closeOnEscape:true,caption:"Search Initiatives",multipleSearch:true,closeAfterSearch:true}
).navButtonAdd('#pager',{
caption:"Export to Excel",
buttonicon:"images/sizzlejs_32x32.png",
onClickButton: function(){
exportExcel();
},
position:"last"
});
function exportExcel()
{
var mya=new Array();
mya=$("#list").getDataIDs(); // Get All IDs
var data=$("#list").getRowData(mya[0]); // Get First row to get the labels
var colNames=new Array();
var ii=0;
for (var i in data){colNames[ii++]=i;} // capture col names
var html="";
for (var k=0;k<colNames.length;k++)
{
if(colNames[k] == "PROJECTID") {
html=html+"EMIT_ID"+"\t";
} else if (colNames[k] == "PROJECT_TITLE") {
html=html+"INITIATIVE_TITLE"+"\t";
} else if (colNames[k] == "PROJECT_TYPE") {
html=html+"SUB-CATEGORY"+"\t";
} else if (colNames[k] == "PROJECT_TYPEID") {
html=html+"SUB_CAT_ID"+"\t";
} else if (colNames[k] == "SUB_TEAM") {
html=html+"SUB_TEAM_MEMBERS"+"\t";
} else if (colNames[k] == "OVERRIDE") {
html=html+"OVERRIDE%_COMP"+"\t";
} else if (colNames[k] == "EM_EXECUTION_TOP_TEN") {
html=html+"EM_EXECUTION_PAIN_POINT"+"\t";
} else {
html=html+colNames[k]+"\t"; // output each Column as tab delimited
}
}
html=html+"\n";
for(i=0;i<mya.length;i++)
{
data=$("#list").getRowData(mya[i]); // get each row
for(j=0;j<colNames.length;j++)
{
html=html+data[colNames[j]]+"\t"; // output each column as tab delimited
}
html=html+"\n"; // output each row with end of line
}
html=html+"\n"; // end of line at the end
document.forms[0].csvBuffer.value=html;
document.forms[0].method='POST';
document.forms[0].action='http://bfops01.edc.cingular.net/excel/csvExport.php'; // send it to server which will open this contents in excel file
document.forms[0].target='_blank';
document.forms[0].submit();
}
//Function will be called when add/edit encounters an error. The returned message is what will be shown to Initiative
function commonError(data){
return "Error Occured during Operation. Please try again";
}
});
You should verify your code in the http://www.jslint.com/. It has many syntax errors. For example, you forget to declare variables iterLimit and j, you should replace ';' after var myGrid = jQuery("#list") to ',' and many other small problems. I recommend you additionally to use integer values for width parameter in many places of the code like jqGrid use ifself.
You main problem seems to me exist because the <div> for the subgrid will be either not created or has no or wrong id element. The code
jQuery("#"+subgrid_id).html("<table id='"+subgrid_table_id+
"' cellpadding='0' cellspacing='0' class='scroll'></table><div id=’" +
pager_id + "’ class=’scroll’></div>");
contain special character ’ instead of '. It should be replaced to
jQuery("#"+subgrid_id).html("<table id='"+subgrid_table_id+
"'></table><div id='" + pager_id + "'></div>");
You use very very old syntax for HTML elements and use retro parameters like imgpath which are deprecated since version 3.5 of jqGrid.

Resources