Similar to the form editing there are cases where we need a dependent drop downs in inline editing. The solution provided seems a little bit complicated, but I hope that with the appropriate explanation this will make it easy to understand.
Definition of the task: There are two fields in our grid view Country and City, where the field City is dependent on the field Country (parent – child). The requirement is to have inline edit with these two editable fields as selects, and when the Country value change, the appropriate list of cities should be loaded into the City field. The data for Country and City obtained from the server is in JSON format.
The grid view has the following description (using the colModel):
[js]
$("#jqGrid").jqGrid({
…
colModel: [
{
label: ‘Customer ID’,
name: ‘CustomerID’,
width: 75,
key: true
},{
label: ‘Company Name’,
name: ‘CompanyName’,
width: 140,
editable: true
},{
label : ‘Phone’,
name: ‘Phone’,
width: 100,
editable: true
},{
label: ‘Postal Code’,
name: ‘PostalCode’,
width: 80,
editable: true
},{
name: ‘Country’,
width: 200,
editable: true
},{
name: ‘City’,
width: 200,
editable: true
}],
…
[/js]
All the fields in colModel have a property
[js]editable:true[/js]
which defines that all of them will be edited.
Before to begin with the code explanation it is good to know that the solution of the problem has two parts – initial part and interaction part.
The initial part will build the selects and will load the appropriate option values into the selects.
The interaction part is responsible for changing the city select options when the Country field has a new value selected from the user.
Before these we need to define the inline editing. The inline editing here will be defined within onSelectRow event using the two inline methods – restoreRow and editRow. For easy manipulation we will define a separate function named editRow
[js]
function editRow(id) {
if (id && id !== lastSelection) {
var grid = $("#jqGrid");
rowdata = grid.getRowData( id );
grid.jqGrid(‘restoreRow’,lastSelection);
grid.jqGrid(‘editRow’,id, {keys:true, focusField: 4});
lastSelection = id;
}
}
[/js]
and then in the grid definition
[js]
…
$("#jqGrid").jqGrid({
…
onSelectRow : editRow,
…
});
[/js]
The variable rowdata, which contain the values of the edited row immediate before editing, is defined as global within scope, and it is needed for obtaining the initial values for the select (initial part).
Initial part
First we need to define that these two fields will be edited as selects and then we need to load the list of the appropriate values. For obtaning an building the values of select of field Country we will use editoptions dataUrl option to obtain the JSON data from the server and buildSelect event in the same editoptions to convert the data from JSON to HTML select. The returned data from server for the County is in the following format
[js]
{
"USA":"USA",
"UK":"UK",
"Canada" : "Canada"
}
[/js]
More info on these options and events can be found here
It is important to note that the buildSelect event with combination of dataUrl expect the data coming from the server to be a HTML, which will not meet our requierment to expect JSON data. In order to tell the script that we expect JSON data we will use ajaxSelectOptions to define the expected type format from server – see code below
To get the appropriate values for the City field we will use dataInit event (see the same link). On this event we will get the value of the selected Country for that row using the rowdata variable in onSelectRow and will pass it to the ajax in order to obtain the appropriate City values. In order not to repeat a code we will create a separate function which contain the ajax call. This function will have two parameters – the html element where to put the builded options for select and the Country which will be passed as parameter for the ajax. We will name this function fillCity. The code for this initial part is as follow
[js]
$("#jqGrid").jqGrid({
…
colModel : [
…
{
name: ‘Country’,
width: 200,
editable: true,
edittype: "select",
editoptions: {
dataUrl : ‘country.json’,
buildSelect : function (cntry) {
// variable to build the select
var s = ‘<select>’;
// check to see if the data provided is JSON
if( $.isPlainObject(cntry)) {
// build the options
for( var key in cntry) {
s += ‘<option value="’+key+’" >’+cntry[key]+'</option>’;
}
}
s += ‘</select>’;
return s;
}
}
},{
name: ‘City’,
width: 200,
editable: true,
edittype: "select",
editoptions: {
value: ":Select a City",
dataInit : function( element, options ) {
// get the selected Country value from rowdata defined
// in onSelectRow and pass it to the function fillCity again with the element
var Country = rowdata.Country;
fillCity( element, Country );
}
}
}
…
],
// the expected data format for select is JSON
ajaxSelectOptions : {
dataType : ‘json’
},
…
});
[/js]
In buildSelect event it is not needed to care about the selected value in the select, since the jqGrid script automatically uses the selected value from the Country field and make the rest of the code. The code of fillCity should care for the initial selection of the City field. The function have the following code:
[js]
function fillCity( element, Country ) {
$.ajax({
url : Country+’.json’,
dataType : "json",
type : "GET",
success : function(data) {
var s = ”;
if( $.isPlainObject(data)) {
var selected;
for( var key in data) {
selected = ”;
// check if the value of city match the selected one
// and if yes set the value to selected.
if( key === rowdata.City) {
selected = ‘ selected="selected"’;
}
s += ‘<option value="’+key+’"’+ selected +’ >’+data[key]+'</option>’;
}
}
$(element).html( s);
}
});
}
[/js]
In this function a jQuery ajax is used and to the url parameter is passed the selected country, so that we know on server which city’s to get. The country can be passed to the data parameter of the ajax too.
The data for City is a JSON and have the following format:
[js]
{
"Vancouver" : "Vancouver",
"Toronto":"Toronto",
"Quebec":"Quebec"
}
[/js]
At this point our Initial part seems to be able to do what we want – i.e to build the selects and set the selected items of Country and City html select.
The next step is to define the action, where when the user changes the Country field the appropriate City values should be loaded. For this purpose a javascript change event can be used. In all editing modules in jqGrid we can use dataEvents property of editoptions to define any javascript action of the edited element. In this event we will get the newly selected Country and will call again a ajax to get the appropriated Cities. The problem which my occur here is: how to know the newly created City select element? Fortunately jqGrid create a uniquie id of each input element with some rules. These rules are described here With other words the id of the select is a combination of the rowId of the row plus the name of the element in colModel. To get the id of the row we will use closest jQuery function to get the needed.
For filling the City select we will again use the fillCity function, defined above. Below is the code of the dataEvents:
[js]
…
{
name: ‘Country’,
width: 200,
editable: true,
edittype: "select",
editoptions: {
dataUrl : ‘country.json’,
buildSelect : function (cntry) {
// variable to build the select
var s = ‘<select>’;
// check to see if the data provided is JSON
if( $.isPlainObject(cntry)) {
// build the options
for( var key in cntry) {
s += ‘<option value="’+key+’" >’+cntry[key]+'</option>’;
}
}
s += ‘</select>’;
return s;
},
dataEvents : [
{
‘type’ : ‘change’,
‘fn’ : function ( el ) {
// get the newly selected value from the user
var Country = $(el.target).val(),
// get the id
var id = $(el.target).closest("tr.jqgrow").attr("id");
// fill the City
if( id && Country) {
fillCity($("#"+id+"_City") , Country );
}
}
}]
}
}
…
[/js]
With this last code we are able to use depended drop downs in inline edit. Of course the code used here can be optimized, but our goal is to show how this can be achieved. The online demo is provided in our site here
Enjoy
Tony
Copyright 2014 TriRand LtdAll Rights ReservedRSS
Back to Top