Using jqGrid as pop up selection

There are situations where we want to use jqGrid as pick up selection list where we can easy search and if desired to add records that are not in the list.

For this purpose we will use jqGrid in inline edit mode and will create a link (button) next to the edited field, which when clicked will call a modal window with another jqGrid to make searching in big data set and select the desired field.

In this case a good solution is to use dataInit event in edit options. As you know this event raises only once when the inline edit field is created. On this event we will build modal dialog on which we will put another grid. The code can be something like this:

colModel : [
...
{
	name : "ShipAddress",
	label: "Address",
	editable: true,
	editoptions: { 
		dataInit: function (element) {
			$(element).css({"width":"75%","float":"left"}).after("<a href='#' style='float:left;margin-left:2px;' class='picker'>SEL</a>");
			$(".picker").click(function(){
                                 var val = $(element).val();
				 pickupdata( element, val );
			});
		},
                dataEvents:[
                         {
                              type: 'click',
                              fn: function(e){
                                 var element = e.target;
                                 var val = $(element).val();
                                 pickupdata(element,val);
                              }
                         },//click event
                         {
                              type: 'keydown',
                              fn: function(e){
                                  e.preventDefault();
                                 var element = e.target;
                                 var val = $(element).val();
                                 pickupdata(element,val);
                              }
                         }
                ]
	}
}
],

...

As can be seen from the fragment we make the field little smaller in order to put a place for the link and then we attach a click event which call pickupdata function. This function is responsible for the creation of the modal which will appear after clicking on the link.

If you want to have a behavior like jQuery UI date picker it is needed to use dataEvents. The following code was added from @krissredy

The code do the following.

  • Position picker dialog below the element.
  • User clicks on any key and picker dialog opens
  • Search field focus set on picker dialog

The function uses jQuery UI dialog, but here we can use any other modal plugin.

function pickupdata( element, val ) {
	var Dialog = $('<div id="dialog" style="display:hidden" title="Select Address"><table id="selector"></table></div>').appendTo('body');
	Dialog.dialog({
		width: 'auto',
		modal:true,
        position: { my: "left top", at: "left bottom", of: $(element) },
		open: function(ev, ui){
			$(".ui-dialog").css('font-size','0.9em');
			pickupgrid( element, val );
		},
		close: function(e,ui) {
			Dialog.remove();
		}
	});
	Dialog.dialog('widget').css('font-size','12px');
}

When the dialog open (open event) we call another function which creates the grid with the necessary options and possibility to search records. The code follow:

function pickupgrid( element,val ) {
	$("#selector").jqGrid({
		url: 'data.json',
		loadonce: true,
		datatype: "json",
		colModel : [
			{
				name : "ShipAddress", label : "Address"
			}
		],
		onSelectRow : function (id, stat, e) {
			var cd = $(this).jqGrid('getCell', id, 0);
			$(element).val( cd );
			$("#dialog").remove();
			$(element).focus();
		},
                // focus search field
                gridComplete:function(data,response){
                     $("#gs_ShipAddress").focus();
                }
	});
	$('#selector').jqGrid('filterToolbar',{searchOnEnter:false});
}

The grid is standard jqGrid. The only that we should pay attention here is the onSelectRow.
As per description the event raises when we select a row. When the row is selected, we get the contents of the selected cell and put it as values in the input element which is passed as parameter in our functions. After this we destroy the modal (which destroy the grid too) and focus the field.

The gridComplete is used to focus the input search field when the modal dialogs is open and grid is constructed.

The demo showing this feature can be started from here

The full source code follow:

         $("#jqGrid").jqGrid({
              url: 'data.php',
              editurl: 'clientArray',
              mtype: "GET",
              datatype: "json",
              page: 1,
              colModel: [
                  { label: 'Order ID', name: 'OrderID', key: true, width: 75 },
                  {
                      label: 'Order Date',
                      name: 'OrderDate',
                      width: 150,
                      editable: true,
                      edittype:"text",
                      editoptions: {
                          // dataInit is the client-side event that fires upon initializing the toolbar search field for a column
                          // use it to place a third party control to customize the toolbar
                          dataInit: function (element) {
                              $(element).datepicker({
                                  id: 'orderDate_datePicker',
                                  dateFormat: 'M/d/yy',
                                  //minDate: new Date(2010, 0, 1),
                                  maxDate: new Date(2020, 0, 1),
                                  showOn: 'focus'
                              });
                          }
                      }
                  },
                   {
                       label: 'Customer ID',
                       name: 'CustomerID',
                       width: 150,
                       editable: true,
                       edittype: "select",
                       editoptions: {
                           value: "ALFKI:ALFKI;ANATR:ANATR;ANTON:ANTON;AROUT:AROUT;BERGS:BERGS;BLAUS:BLAUS;BLONP:BLONP;BOLID:BOLID;BONAP:BONAP;BOTTM:BOTTM;BSBEV:BSBEV;CACTU:CACTU;CENTC:CENTC;CHOPS:CHOPS;COMMI:COMMI;CONSH:CONSH;DRACD:DRACD;DUMON:DUMON;EASTC:EASTC;ERNSH:ERNSH;FAMIA:FAMIA;FISSA:FISSA;FOLIG:FOLIG;FOLKO:FOLKO;FRANK:FRANK;FRANR:FRANR;FRANS:FRANS;FURIB:FURIB;GALED:GALED;GODOS:GODOS;GOURL:GOURL;GREAL:GREAL;GROSR:GROSR;HANAR:HANAR;HILAA:HILAA;HUNGC:HUNGC;HUNGO:HUNGO;ISLAT:ISLAT;KOENE:KOENE;LACOR:LACOR;LAMAI:LAMAI;LAUGB:LAUGB;LAZYK:LAZYK;LEHMS:LEHMS;LETSS:LETSS;LILAS:LILAS;LINOD:LINOD;LONEP:LONEP;MAGAA:MAGAA;MAISD:MAISD;MEREP:MEREP;MORGK:MORGK;NORTS:NORTS;OCEAN:OCEAN;OLDWO:OLDWO;OTTIK:OTTIK;PARIS:PARIS;PERIC:PERIC;PICCO:PICCO;PRINI:PRINI;QUEDE:QUEDE;QUEEN:QUEEN;QUICK:QUICK;RANCH:RANCH;RATTC:RATTC;REGGC:REGGC;RICAR:RICAR;RICSU:RICSU;ROMEY:ROMEY;SANTG:SANTG;SAVEA:SAVEA;SEVES:SEVES;SIMOB:SIMOB;SPECD:SPECD;SPLIR:SPLIR;SUPRD:SUPRD;THEBI:THEBI;THECR:THECR;TOMSP:TOMSP;TORTU:TORTU;TRADH:TRADH;TRAIH:TRAIH;VAFFE:VAFFE;VICTE:VICTE;VINET:VINET;WANDK:WANDK;WARTH:WARTH;WELLI:WELLI;WHITC:WHITC;WILMK:WILMK;WOLZA:WOLZA"
                       }
                   },
                  {
                      label: 'Freigh',
                      name: 'Freight',
                      width: 150,
                      sorttype:"number",
                      editable: true,
                      align : "right"
                  },
                  {
                      label: 'Ship Name',
                      name: 'ShipName',
                      width: 150,
                      editable: true,
                      edittype: "text",
                      editoptions: {
                          // dataInit is the client-side event that fires upon initializing the toolbar search field for a column
                          // use it to place a third party control to customize the toolbar
                          dataInit: function (element) {
                              window.setTimeout(function () {
                                  $(element).autocomplete({
                                        id: 'AutoComplete',
                                        source: function(request, response){
                                        this.xhr = $.ajax({
                                          url: 'http://trirand.com/blog/phpjqgrid/examples/jsonp/autocompletep.php?callback=?&acelem=ShipName',
                                          data: request,
                                          dataType: "jsonp",
                                          success: function( data ) {
                                              response( data );
                                          },
                                          error: function(model, response, options) {
                                              response([]);
                                          }
                                      });
                                  },
                                  autoFocus: true
                                  });
                              }, 100);
                          }
                      }
                  },
                  {
                      name : "ShipAddress",
                      label: "Address",
                      editable: true,
                      editoptions: {
                          dataInit: function (element) {
                              $(element).css({"width":"75%","float":"left"}).after("<a href='#' style='float:left;margin-left:2px;' class='picker'></a>");
                              $(".picker").click(function(){
                                  var val = $(element).val();
                                  pickupdata(element,val);
                              });
                          },
                          dataEvents:[
                            {
                              type: 'click',
                              fn: function(e){
                                 var element = e.target;
                                 var val = $(element).val();
                                 pickupdata(element,val);
                              }
                            },//click event
                            {
                              type: 'keydown',
                              fn: function(e){
                                  e.preventDefault();
                                 var element = e.target;
                                 var val = $(element).val();
                                 pickupdata(element,val);
                              }
                            }
                          ]
                      }
                  }
              ],
              loadonce : true,
              onSelectRow: editRow, // the javascript function to call on row click. will ues to to put the row in edit mode
              viewrecords: true,
              width: 750,
              height: 250,
              rowNum: 20,
              pager: "#jqGridPager"
          });

    var lastSelection;

    function editRow(id) {
        if (id && id !== lastSelection) {
            var grid = $("#jqGrid");
            grid.jqGrid('restoreRow',lastSelection);
            grid.jqGrid('editRow',id, {keys:true, focusField: 1});
            lastSelection = id;
        }
    }
    function pickupdata(element,val) {
        var Dialog = $('<div id="dialog" style="display:hidden" title="Select Address"><table id="selector"></table></div>').appendTo('body');
        Dialog.dialog({
            width: 'auto',
            modal:true,
            position: { my: "left top", at: "left bottom", of: $(element) },
            open: function(ev, ui){
                $(".ui-dialog").css('font-size','0.9em');
                pickupgrid(element,val);
            },
            close: function(e,ui) {
                Dialog.remove();
            }
        });
        Dialog.dialog('widget').css('font-size','12px');
    }
    function pickupgrid(element,val) {
        var mygrid = $("#selector").jqGrid({
            url: 'data.php',
            loadonce: true,
            datatype: "json",
            colModel : [
                {
                    name : "ShipAddress", label : "Address"
                }
            ],
            onSelectRow : function (id, stat, e) {
                var cd = $(this).jqGrid('getCell', id, 0);
                $(element).val( cd );
                $("#dialog").remove();
                $(element).focus();
            },
            gridComplete:function(data,response){
              $("#gs_ShipAddress").focus();
            }
        });
        $('#selector').jqGrid('filterToolbar',{searchOnEnter:false});
    }        });

5 Comments

  1. Kris says:

    This is awesome! Thank you for posting this tutorial.
    The only thing I would like to add this – for usability reasons – picker model pops up when user clicks or tabs into the cell and hides when clicked out of the cell and destroyed when edit mode is closed or user presses ESC key

    How would I achieve this. Would I use dataEvents?

  2. mrp4 says:

    new to this tool. how do you change the query in the selection grid do a like comparison instead of just looking for things that are an exact match to the beginning chars of the string?

    also is this doing a database query every time you search or doing a memory lookup client side?

  3. tony says:

    @Kris,

    I have answered this in the forum here: http://guriddo.net/?topic=feature-suggestion.

    @Mrp4
    There are two possible scenarios.
    1. Used in the example – all the data is loaded at a client side and we can search when we type a char.
    2. We need to put the search string and push enter to perform the search.

    Th first is used if there are not relative big data set while the second is used to query the database. Of course we can configure database search while type, but it all depends on to many conditions.

    Regards

  4. Kris says:

    Here’s couple of things I added – don’t know if it is the right way to do
    1. position picker dialog below the element
    2. user clicks on any key and picker dialog opens
    3. search field focus set on picker dialog

    here’s the demo
    http://50.53.76.235:90/jqgrid/gridAsPicker.php

  5. tony says:

    Thank you Kris,

    I have added your additions in the article.

    Kind Regards,
    Tony

Leave a comment

Stay connected with us in your favorite flavor!