In this advanced tutorial we will use the code from our online example framework) "SubGrid (2 nested levels)" as a base and add other useful features often needed in real-world scenarios.

  1. We will enable editing in both parent and child grids.
  2. We will add an additional parameter to the subgrid (from parent) when a new record is inserted in order to sync both grids.
  3. When we delete a record in the parent grid, all associated records from the child grid will be deleted as well.
  4. We will use some of the additional functionality that the jqGrid database driver provides.

In order to achieve this we will create two PHP code files - one for the parent grid and another for the child grid.

grid.php code (parent grid)

// include the database connection settings require_once 'jq-config.php'; // include the jqGrid class require_once "php/jqGrid.php"; // include the driver class require_once "php/jqGridPdo.php"; // connection to the server $conn = new PDO(DB_DSN,DB_USER,DB_PASSWORD); // instruct the database that we will be using utf-8 encoding $conn->query("SET NAMES utf8"); // create the jqGrid instance $grid = new jqGridRender($conn); // set the SQL select query $grid->SelectCommand = 'SELECT CustomerID, CompanyName, ContactName, Phone, City FROM customers'; // instruct jqgrid to use the "customers" table and set primary keys needed for CRUD (create, read, update, delete) operations $grid->table = 'customers'; $grid->setPrimaryKeyId('CustomerID'); $grid->serialKey = false; // Set output format to json $grid->dataType = 'json'; // let the grid automatically create the columns model based on the database table $grid->setColModel(); // set the url to the location of the PHP code file for the respective grid $grid->setUrl('grid.php'); // set some grid options $grid->setGridOptions(array( "rowNum"=>10, "height"=>250, "rowList"=>array(10,20,30), "sortname"=>"CustomerID" )); $grid->setColProperty('CustomerID', array("label"=>"ID", "width"=>50)); // set the url to the location of the PHP code file for the respective grid $grid->setSubGridGrid("subgrid.php"); // enable navigator $grid->navigator = true; // disable the delete operation programatically for that table $grid->del = false; // we need to write some custom code when we are in delete mode. // get the grid operation parameter to see if we are in delete mode // jqGrid sends the "oper" parameter to identify the needed action $deloper = $_POST['oper']; // det the customer id $custid = $_POST['CustomerID']; // if the operation is del and the customerid is set if($deloper == 'del' && isset($custid) ) { // the two tables are linked via CustomerID, so let try to delete the records in both tables try { jqGridDB::beginTransaction($conn); $cust = jqGridDB::prepare($conn, "DELETE FROM customers WHERE CustomerID= ?", array($custid)); $order = jqGridDB::prepare($conn,"DELETE FROM orders WHERE CustomerID = ?", array($custid)) jqGridDB::execute($cust); jqGridDB::execute($order); jqGridDB::commit($conn); } catch(Exception $e) { jqGridDB::rollBack($conn); echo $e->getMessage(); } } $grid->renderGrid('#grid','#pager',true, null, null, true,true); $conn = null; ?>

With the command

$grid->setSubGridGrid("subgrid.php");
we set the main grid in subgrid mode expecting content from this url for the child grid.

Next we disable jqGrid's automatic deleting of records in the parent grid. By default, automatic deleting will delete the parent row only, whereas we also want to delete all related records in the child grid as well. This is done via

$grid->del = false;
In this case we should manually determine if we are in delete mode and manually delete the parent row and all related child rows. jqGrid does this by setting the "oper" post parameter. If the parameter "oper" equals "del", then we know we are in delete mode and can proceed with the logic needed. In addition to that, the grid sends the data for the row deleted, including the primary key (CustomerID in our case). For example:

// get the operation $deloper = $_POST['oper']; // det the customer id $custid = $_POST['CustomerID']; // if the operation is del and the customerid is set if($deloper == 'del' && isset($custid) ) { ...

At end we enclose the deletion in transaction deleting the desired records in both tables in order to make sure the tables are in sync.

Now, lets look at the subgrid PHP code file:

subgrid.php

<?php // inclide the database connection settings require_once 'jq-config.php'; // include the jqGrid Class require_once "php/jqGrid.php"; // include the driver class require_once "php/jqGridPdo.php"; // connection to the server $conn = new PDO(DB_DSN,DB_USER,DB_PASSWORD); // instruct the db that we use utf-8 encoding $conn->query("SET NAMES utf8"); // Get the needed parameters passed from the main grid // By default we add to postData subgrid and rowid parameters in the main grid $subtable = jqGridUtils::Strip($_REQUEST["subgrid"]); $rowid = jqGridUtils::Strip($_REQUEST["rowid"]); // create the jqGrid instance $grid = new jqGridRender($conn); // set the SQL select query $grid->SelectCommand = "SELECT OrderID, RequiredDate, ShipName, ShipCity, Freight FROM orders WHERE CustomerID = ?"; // set the ouput format to json $grid->dataType = 'json'; // instruct the grid the we are using the "orders" datatable $grid->table = "orders"; $grid->setPrimaryKeyId("OrderID"); // Let the grid create the column model automatically $grid->setColModel(null,array(&$rowid)); // Set the url from where we obtain the data $grid->setUrl('subgrid.php'); // Set some grid options $grid->setGridOptions(array( "width"=>540, "rowNum"=>10, "sortname"=>"OrderID", "height"=>110, "postData"=>array("subgrid"=>$subtable,"rowid"=>$rowid)) ); // set a option when we add a record to insert a CustomerID too. $grid->setNavOptions("add",array("editData"=>array("CustomerID"=>$rowid))); // Change some property of the field(s) $grid->setColProperty("RequiredDate", array( "formatter"=>"date", "formatoptions"=>array("srcformat"=>"Y-m-d H:i:s","newformat"=>"m/d/Y"), "search"=>false ) ); // enable editing $grid->navigator = true; $subtable = $subtable."_t"; $pager = $subtable."_p"; $grid->renderGrid($subtable,$pager, true, null, array(&$rowid), true,true); $conn = null; ?>

In the subgrid code there is nothing special except this line of code

$grid->setNavOptions("add",array("editData"=>array("CustomerID"=>$rowid)));

With this line we set additional parameter when we are in add mode and this is the id of the Customer. The variable is posted and inserted succesfully.