while the select editoption posts the value (or id) of the selected list item, autocomplete posts the label - i need id posted - jqgrid

While both autocomplete and select in jqgrid editform place the selected label into the cell, select will place the value (id) in the postdata array where autocomplete will place the label into the postdata array.
is there a way to get the editoption's autocomplete to post the item value (id) instead of the label?
here is the jqgrid code segment i'm using autocomplete in...
$('#tab3-grid').jqGrid({
colNames:['Workorder', 'wo.CUID',.....],
colModel:[
.
.
.
{name:'wo.CUID', index:'cu.LastName', width:120, fixed:true, align:'center', sortable:true, editable:true, edittype:'text',
editoptions:{dataInit:function(el){$(el).autocomplete({ source: 'php/customer-ac-script.php'
, minLength: 1
})
}
},
formoptions:{rowpos: 1, label:'Customer', elmprefix:'* '},
editrules:{required:true}
},
.
.
.
$('#tab3-grid').jqGrid('navGrid', '#tab3-pager',
{view:true, closeOnEscape:true, cloneToTop:true}, // general parameters that apply to all navigation options below.
{jqModal:true, navkeys:[true,38,40], savekey:[true,13]}, // edit options.
{jqModal:true, navkeys:[true,38,40], savekey:[true,13], reloadAfterSubmit:false, afterSubmit: addRecordID}, // add options.
{jqModal:true, afterSubmit: serverMessage}, // del options.
{jqModal:true}, // search options.
{jqModal:true, navkeys:[true,38,40]} // view options.
);
The php code segment:
// construct autocomplete select.
$i = 0;
while($row = mysql_fetch_assoc($result)) {
$output[$i][$crudConfig['id']] = $row['CUID'];
$output[$i][$crudConfig['value']] = $row['LastName'];
logMsg(__LINE__,'I','cu.CUID: '.$row['CUID'].', cu.LastName: '.$row['LastName']);
$i++;
}
// encode to json format and send output back to jqGrid table.
echo json_encode($output);
logMsg(__LINE__,'I','Send json output back to jqGrid table: '.json_encode($output));
Would it be as simple as calling a function under the autocomplete select event or the grid before or after editform submit?
Also, i noticed this note in the jqgrid doc's for datainit: that says...
Note: Some plugins require the position of the element in the DOM and
since this event is raised before inserting the element into the DOM
you can use a setTimeout function to accomplish the desired action.
Would the lack of including the settimeout function be causing the problem?

The server code which provide the JSON response on the autocomplete request has id and value properties. On the other side the standard behavior of jQuery UI Autocomplete is to use label and value properties (see "Datamodel" in the documentation). The value of label property (if any exist) will be used to display in the contextmenu. The value of value property will be placed in the <input> field after the user choose the item from the contextmenu. The value of label property can has HTML markup, but the value of value property must be the text.
So I see the problem as pure problem of the usage of jQuery UI Autocomplete independent on jqGrid. If I understand correct your question you can solve your problem by modification your server side code.

Oleg's answer clarifying the data model for jquery UI's autocomplete, has allowed me to move forward and understand that autocomplete has nothing to do with constructing and sending the postdata array to the server, jqgrid's editform handles it. With that knowledge, i was able to answer my original question and successfully integrate autocomplete into jqgrid. So, in the interest of sharing, i'd like to show you all my motivation and solution.
By default, selecting a label from the autocomplete list put's the value of the selected label/value pair into the text box. All the editform cares about when you submit is what's in the edit fields. So when you submit the editform, the cell's postdata element value will again contain the value of the autocomplete text box. But what if while wanting to post the value of the label/value pair, you want the label of the label/value pair displayed in the text box? You have a problem! How do you get the value of the label/value pair posted to the server?
Well, after spending a few days on it, it turns out to be quite simply. While i'm sure there is more than one solution, here is mine:
add a hidden id column in the grid
define the select: and focus: events in the autocomplete function
in the select: function; insert the selected label into the text box (optional), disable the default behavior of autocomplete, then set the cell of the hidden column to the value of the selected label/value pair
in the focus: function; insert the selected label into the text box(optional), disable the default behavior of autocomplete
add an "onclickSubmit:" event to the navgrid edit options with function name something like "fixpostdata"
in the "fixpostdata" function; get the cell value of the hidden column and insert it into the postdata element associated with the cell.
The following are the grid and javascript code segments i used…
grid segments
{name:'wo_CUID', index:'wo_CUID', width: 70, hidden: true},
{name:'wo.CUID', index:'cu.LastName', width:120, sortable:true, editable:true, edittype:'text',
editoptions:{
dataInit:function(el){ // el contains the id of the edit form input text box.
$(el).autocomplete({
source: 'php/customer-ac-script.php',
minLength: 1,
select: function(event, ui){event.preventDefault();
$(el).val(ui.item.label);
var rowid = $('#tab3-grid').getGridParam('selrow');
// set the hidden wo_CUID cell with selected value of the selected label.
$('#tab3-grid').jqGrid('setCell', rowid,'wo_CUID',ui.item.value);},
focus: function(event, ui) {event.preventDefault();
$(el).val(ui.item.label);}
})
}
},
formoptions:{rowpos: 1, label:'Customer', elmprefix:'* '},
editrules:{required:true}
},
.
.
$('#tab3-grid').jqGrid('navGrid', '#tab3-pager',
{view:true, closeOnEscape:true, cloneToTop:true},
{jqModal:true, navkeys:[false,38,40], onclickSubmit: fixpostdata}, // edit options.
.
.
javascript function
// define handler function for 'onclickSubmit' event.
var fixpostdata = function(params, postdata){
var rowid = $('#tab3-grid').getGridParam('selrow');
var value = $('#tab3-grid').jqGrid('getCell', rowid,'wo_CUID');
postdata['wo.CUID'] = value;
return;
}
The fixpostdata function fires when you submit the editform but befor the postdata array is sent to the server. At this point you replace the cell's postdata element value with whatever you want. In this case, the value of the label/value pair stored in the hidden column cell. When the function returns, the modified postdata array is sent to the server.
Done!

Related

JQGrid - toggling multiselect

Is there a way to toggle the multiselect option of a grid?
Changing the multiselect parameter of the grid and calling for a reload has the side-effect of leaving the header behind when disabling or not creating the header column if multiselect was not TRUE upon the grid creation.
The closest I have come is setting multiselect to TRUE upon grid creation and using showCol and hideCol to toggle: $('#grid').showCol("cb").trigger('reloadGrid');
This has a side effect of changing the grid width when toggled. It appears the cb column width is reserved when it is not hidden.
Basically I'm attempting to create a grid with an "edit/cancel" button to toggle the multiselect -- very similar to how the iPhone/iPad handles deleting multiple mail or text messages.
Thank you in advance.
I full agree with Justin that jqGrid don't support toggling of multiselect parameter dynamically. So +1 to his answer in any way. I agree, that the simplest and the only supported way to toggle multiselect parameter will be connected with re-initialize (re-creating) the grid.
So if you need to change the value of multiselect parameter of jqGrid you need first change multiselect parameter with respect of respect setGridParam and then re-creating the grid with respect of GridUnload method for example. See the demo from the answer.
Nevertheless I find your question very interesting (+1 for you too). It's a little sport task at least to try to implement the behavior.
Some remarks for the understanding the complexity of the problem. During filling of the body of the grid jqGrid code calculate positions of the cells based on the value of multiselect parameter (see setting of gi value here and usage it later, here for example). So if you will hide the column 'cb', which hold the checkboxes, the cell position will be calculated wrong. The grid will be filled correctly only if either the column 'cb' not exists at all or if you have multiselect: true. So you have to set multiselect: true before paging or sorting of the grid if the column 'cb' exist in the grid. Even for hidden column 'cb' you have to set multiselect to true. On the other side you have to set multiselect to the value which corresponds the real behavior which you need directly after filling of the grid (for example in the loadComplete).
I hope I express me clear inspite of my bad English. To be sure that all understand me correctly I repeat the same one more time. If you want try to toggle multiselect dynamically you have to do the following steps:
create grid in any way with multiselect: true to have 'cb' column
set multiselect: false and hide 'cb' column in the loadComplete if you want to have single select behavior
set multiselect: true always before refreshing the grid: before paging, sorting, filtering, reloading and so on.
I created the demo which seems to work. It has the button which can be used to toggle multiselect parameter:
In the demo I used the trick with subclassing (overwriting of the original event handle) of reloadGrid event which I described the old answer.
The most important parts of the code from the demo you will find below:
var events, originalReloadGrid, $grid = $("#list"), multiselect = false,
enableMultiselect = function (isEnable) {
$(this).jqGrid('setGridParam', {multiselect: (isEnable ? true : false)});
};
$grid.jqGrid({
// ... some parameters
multiselect: true,
onPaging: function () {
enableMultiselect.call(this, true);
},
onSortCol: function () {
enableMultiselect.call(this, true);
},
loadComplete: function () {
if (!multiselect) {
$(this).jqGrid('hideCol', 'cb');
} else {
$(this).jqGrid('showCol', 'cb');
}
enableMultiselect.call(this, multiselect);
}
});
$grid.jqGrid('navGrid', '#pager', {add: false, edit: false, del: false}, {}, {}, {},
{multipleSearch: true, multipleGroup: true, closeOnEscape: true, showQuery: true, closeAfterSearch: true});
events = $grid.data("events"); // read all events bound to
// Verify that one reloadGrid event hanler is set. It should be set
if (events && events.reloadGrid && events.reloadGrid.length === 1) {
originalReloadGrid = events.reloadGrid[0].handler; // save old
$grid.unbind('reloadGrid');
$grid.bind('reloadGrid', function (e, opts) {
enableMultiselect.call(this, true);
originalReloadGrid.call(this, e, opts);
});
}
$("#multi").button().click(function () {
var $this = $(this);
multiselect = $this.is(":checked");
$this.button("option", "label", multiselect ?
"To use single select click here" :
"To use multiselect click here");
enableMultiselect.call($grid[0], true);
$grid.trigger("reloadGrid");
});
UPDATED: In case of usage jQuery in version 1.8 or higher one have to change the line events = $grid.data("events"); to events = $._data($grid[0], "events");. One can find the modified demo here.
I really like what you are trying to do here, and think it would be a great enhancement for jqGrid, but unfortunately this is not officially supported. In the jqGrid documentation under Documentation | Options | multiselect you can see the Can be changed? column for multiselect reads:
No. see HOWTO
It would be nice if there was a link or more information about that HOWTO. Anyway, this is probably why you are running into all of the weird behavior. You may be able to work around it if you try hard enough - if so, please consider posting your solution here.
Alternatively, perhaps you could re-initialize the grid in place and change it from/to a multi-select grid? Not an ideal solution because the user will have to wait longer for the grid to be set up, but this is probably the quickest solution.
A simpler answer:
<input type="button" value="Multiselect" onclick="toggle_multiselect()">
<script>
function toggle_multiselect()
{
if ($('#list1 .cbox:visible').length > 0)
{
$('#list1').jqGrid('hideCol', 'cb');
jQuery('.jqgrow').click(function(){ jQuery('#list1').jqGrid('resetSelection'); this.checked = true; });
}
else
{
$('#list1').jqGrid('showCol', 'cb');
jQuery('.jqgrow').unbind('click');
}
}
</script>
Where list1 is from <table id="list1"></table>.

Need to pass a jqgrid column name to function triggered by the "onclickSubmit" event

I need to pass or make available a jqgrid colModel column name to a function triggered by the jqgrid event "onclickSubmit:" defined in the edit options of navGrid - but i don't know how to do that.
here are the jqgrid and javascript code segments:
..., onclickSubmit: fixpostdata}, // navGrid edit options
.
.
.
var fixpostdata = function(params, postdata){
var rowid = $('#tab3-grid').getGridParam('selrow');
// when the onclickSubmit event fires and calls this function,
// a string containing a jqgrid colmodel column name needs to be
// made available in order to modify that cell's value contained
// in the postdata array prior to posting it to the server.
columnName = ???;
var value = $('#tab3-grid').jqGrid('getCell', rowid, columnName );
postdata[ columnName ] = value;
return;
}
Can anyone help?
also,
what's contained in the params argument?
If you need to send contain of some hidden column to the server together with other editable columns you need include editable: true in the hidden column and add one more property
editrules: { edithidden: false }

How to set default field values for add form in jqgrid from current row

Add toolbar button is used to add new row to jqgrid.
Add form which appears contains all filed vlaues empty.
How to set add form field values from column values from row which was current/selected when add command was issued ?
json remote data is used. Or if this is simpler, how to call server method passing current/selected row to retrieve default values for add form from server ?
jqgrid contains also hidden columns. If possible values from hidden columns from current row should also sent to add controller if add form is saved.
Update
I tried to use Oleg great suggestion by using
afterShowForm: function(formID) {
var selRowData,
rowid = grid.jqGrid('getGridParam', 'selrow');
if (rowid === null) {
// todo: how to cancel add command here
alert('Please select row');
return;
}
selRowData = grid.jqGrid('getRowData', rowid);
if (selRowData === null) {
alert('something unexpected happened');
return;
}
$('#' + 'Baas' + '.FormElement', formID).val(selRowData.Baas);
}
Application keeps add form open after saving. After first save Baas field is empty. It looks like afterShowForm event runs only once, not after every save. How to fix this so that multiple rows with default values can added without closing add form?
How to cancel or not allow Add command if there is no selected row ?
If you need to make some initialization actions only for Add form you can use at least two approaches:
the usage of defaultValue property as function inside of editoptions. The callback function defaultValue can provide the value for the corresponding field of the Add form based of the data from selected row. For optimization purpose you can read the data from the current selected row once in the beforeInitData callback/event. You can just read the data which you need or make an synchronous call to the server to get the information which you need. The only disadvantage of the usage of defaultValue property is that it uses jQuery.val method to set the default value for all fields of Add form with exception 'checkbox' edittype. For the checkboxs jqGrid set checked property of the checkbox of false, 0, no, off or undefined are not found in the value returned by defaultValue property. So the approach will not work for other edittypes. For example it can fail for the custom edittype.
the usage of beforeShowForm or afterShowForm. Inside of the callback functions you can set any value of the form. You can find the filed of the corresponding column of the grid by id of the field which is the same as the value of name property of the corresponding column.
Like you already knows you can get the id of the current selected row with respect of getGridParam and get the data from the selected row
var selRowData, rowid = grid.jqGrid('getGridParam', 'selrow');
if (rowid !== null) {
// a row of grid is selected and we can get the data from the row
// which includes the data from all visible and hidden columns
selRowData= grid.jqGrid('getGridParam', 'selrow');
}
where grid is jQuery object like $('#list') which selects the main <table> element of the grid.
In the demo you can see how works the first approach described above.

jqGrid does not selects cell value as a selected dorp down value In edit mode

I am using jqGrid v 4.0 in my application to display tabuler data with Inline edit feature. One of the column in the Grid is a type of "Select". I have populated this select with following server side code:
//get all Departments
HRDept = $.ajax({
url: '../../PerformanceReview/GetHRDepartments/',
async: false,
success: function(data, result) {
if (!result)
alert('Failure to retrieve the HR Departments.');
}
}).responseText;
I have populated the Grid column with following sysntax:
name: 'HRDepartment', index: 'Department', align: 'left', editable: true, edittype: 'select', editoptions: {value: HRDept}
But on click of edit button (inline), it shows dropdown on on top of cell but the value is not equal to current cell value. it is always first value of drop down. I had compared the text which i am populating while loading Grid with the text of Dropdown and they are matching.
Could some one help me to set dropdown value similar as cell value.
Your edit options look wrong, it should be "value:text;" and the value should match your data results.
{ ... editoptions: {value: "HRDept:HR Department;" }}
You can checkout the demo of Row Edition -> Input Types at the jqGrid Demo site., which includes a dropdown list edit cell.
If you get the select values from the server you should use dataUrl option of the editoptions instead of value. Then the jqGrid will make the Ajax request at the beginning of the editing and fill the select element with the server response. It is important to understand that the server response should be in another form:
<select>
<option value='101 - Equity Partners'>101 - Equity Partners</option>
…
</select>
If you have already the code on the server which provide the information in another format and you can't change the server code you can define additional buildSelect function which get as the parameter the server response and should return the data in the above format ('...'). See UPDATED part of the answer for the code example.

how to create first column value of jqgrid as iframe window?

In the jqgrid, when i click the first column value, i want to open as iFRAME window. if i use showlink or link formatter, its posted and redirect to the another page. how to create first column value as iframe window.
Thanks in avance..
One method is to use a link to the same page in your format options:
formatoptions: {baseLinkUrl: '#', showAction: '', addParam: ''}
Then after the grid is rendered - for example, in the loadComplete event - set up a click event handler for when a link is clicked:
jQuery('.ui-jqgrid-btable a', '#container').each(function()
{
jQuery(this).unbind('click');
jQuery(this).click(function(){
var link = jQuery(this).attr('href');
var equalPosition = link.indexOf('='); // Get the position of '='
var id = link.substring(equalPosition + 1); // Split the string and get the number.
// Your iframe code here...
return true;
});
This code simply parses out the link, gets the ID, and then lets to do whatever you want with that ID . So for example, you could load content into a new iFrame.
#container is optional, but you could use this as a div that contains the jqGrid div, if you have multiple grids on the same page and need to differentiate them.

Resources