Archive › Examples

Introduction

If you are new to phpGrid, we recommend that you go through the examples in the sequence provided for each section.

Before you begin, make sure that you have installed and configured phpGrid properly. phpGrid utilizes jQuery extensively, the popular cross-browser Javascript framework. The current phpGrid supports jQuery version 1.9.0. If you are already using jQuery but a different version, considering removing the existing jQuery to avoid version conflicts. If you have questions regarding this, please send us an email.

Please note, certain features, such as update, delete, and add new are disabled in online demo for security reason. In addition to the examples, major phpGrid features can be seen in Screenshots page.

Comments ( 0 )

A Basic PHP Datagrid

The basic PHP datagrid requires only as little as TWO lines of code. First of all, always create phpGrid object in the first line; then call its methods to define properties, and lastly always call display() to render to screen.
.
Please note in some databases, such as Firebird, MS Access, the fields name are case-sensitive. Make sure the name used in the code matches the case when you are using those type of databases.
.
  • parameter 1: SQL statement
  • parameter 2: SQL primary key
  • parameter 3: SQl table name

Do NOT include WHERE clause in $sql. Instead use set_query_filter method (version 4.2+) to set query filter.
Note that the 3rd parameter is ALWAYS equals to the database table name, not alias or any arbitrary name (see below).

constructor guide

See Live Example!

Programming Tip: Database Naming Standards

It’s generally not recommended to have dash or space character in naming database tables, or you must add surrounding quotes, or backticks to the table names or columns that have those characters in the query.

Underscore character, on the other hand, is generally accepted for naming convention.

Example:

1
2
SELECT * FROM `my-table` -- requires ` around table name
SELECT * FROM my_table  -- does not require surrounding quotes.
Comments ( 0 )

Descriptive Column Headers

By default phpGrid pulls out the data field name defined in database as the header for each column. You can simply change the title using method set_col_title().

1
2
3
4
5
6
7
8
9
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber", "Customer No.");

$dg -> display();

See Live Example!

Comments ( 0 )

Hide Column

For columns need not to be shown, such as primary key, use method set_col_hidden() to hide those columns. To hide column in both datagrid and form, set the second parameter to false. This is useful to hide the auto increment primary key field from edit form.

Very Important:
The data are still sent to web browser but hidden using CSS display:none. For sensitive data such as passwords and SSN etc, do not use this method, instead do not include those fields in your SQL at all.
 
1
2
3
4
5
6
7
8
9
10
11
12
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber", "Customer No.");
 
// hide a column
$dg -> set_col_hidden("requiredDate");
 
$dg -> display();

See Live Example!

Comments ( 0 )

Datagrid Caption

By default, phpGrid displays table name as the caption. It can be changed using set_caption(). You can also hide the caption by using an empty string “” as the caption.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg->set_col_title("orderNumber", "Order No.");
$dg->set_col_title("orderDate", "Order Date");
$dg->set_col_title("shippedDate", "Shipped Date");
$dg->set_col_title("customerNumber", "Customer No.");
 
// hide a column
$dg -> set_col_hidden("requiredDate");

// change default caption
$dg -> set_caption("Orders List");
 
$dg -> display();

See Live Example!

Comments ( 0 )

Excel, HTML, PDF, or CSV Export

phpGrid currently supports export in native Excel format, CSV, PDF, and HTML format. When the export feature is enabled, phpGrid displays an export icon in the footer. Also see enable_export().

PDF and CSV formats are now supported (Available to Professional License and up) !

export_icons

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
// change column titles
$dg->set_col_title("orderNumber", "Order No.");
$dg->set_col_title("orderDate", "Order Date");
$dg->set_col_title("shippedDate", "Shipped Date");
$dg->set_col_title("customerNumber", "Customer No.");
// hide a column
$dg->set_col_hidden("requiredDate");
// change default caption
$dg->set_caption("Orders List");
// EXCEL export
$dg->enable_export('PDF');
$dg->display();


$dg2 = new C_DataGrid("select * from customers", "customerNumber", "Customers");
// PDF export
$dg2->enable_export('EXCEL');
$dg2->display();

See Live Example!

Comments ( 0 )

Integrated Search

phpGrid includes integrated search. By default, this feature is not enabled. To enable search use enable_search() method with parameter set to true. Once enabled, the integrated search can be toggled with the search button on the footer.

Notice the “status” is automatically rendered as a drop-down in the integrated search(v5.5+). Talking about making your life easy? :)

To always display the search toolbar, please see Always display integrated search toolbar on KB.

integrated_search_dropdown

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$dg = new C_DataGrid("SELECT * FROM Orders", "orderNumber", "Orders");

// change column titles
$dg->set_col_title("orderNumber", "Order No.");
$dg->set_col_title("orderDate", "Order Date");
$dg->set_col_title("shippedDate", "Shipped Date");
$dg->set_col_title("customerNumber", "Customer No.");
 
// hide a column
$dg -> set_col_hidden("requiredDate");

// change default caption
$dg -> set_captin("Orders List");

// set export type and edit select type
$dg -> enable_export('EXCEL');
$dg -> enable_edit('FORM', 'CRUD');
$dg -> set_col_edittype('status', 'select', 'Open:Open;Shipped:Shipped;Cancelled:Cancelled;Disputed:Disputed;On Hold:On Hold');

// enable integrated search
$dg -> enable_search(true);
 
$dg -> display();

See Live Example!

Comments ( 0 )

Set Height and Width

Use set_dimension() method to specify data grid initial height and width. The default height and width is 400 by 300 pixels. In this example, the width is set to 800 pixel, and height is set to 600 pixel.

Wait, It looks funny! The datagrid height is taller than the space used by the number of rows in a page. To fix this, we can set a bigger pagination to accommodate a taller grid. See the next example on pagination.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg->set_col_title("orderNumber", "Order No.");
$dg->set_col_title("orderDate", "Order Date");
$dg->set_col_title("shippedDate", "Shipped Date");
$dg->set_col_title("customerNumber", "Customer No.");
 
// hide a column
$dg -> set_col_hidden("requiredDate");

// change default caption
$dg -> set_caption("Orders List");

// set export type
$dg -> enable_export('EXCEL');

// enable integrated search
$dg -> enable_search(true);

// set height and weight of datagrid
$dg -> set_dimension(800, 600);
 
$dg -> display();

See Live Example!

Comments ( 0 )

Datagrid Pagination

By default, the pagination size is 20. It means maximum of 20 records can be displayed in a page. This value can be easily changed with set_pagesize() method. Be aware that pagination is disabled when set_scroll() is set to true. See the next example on set_scroll() for more information.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg->set_col_title("orderNumber", "Order No.");
$dg->set_col_title("orderDate", "Order Date");
$dg->set_col_title("shippedDate", "Shipped Date");
$dg->set_col_title("customerNumber", "Customer No.");
 
// hide a column
$dg -> set_col_hidden("requiredDate");

// change default caption
$dg -> set_caption("Orders List");

// set export type
$dg -> enable_export('EXCEL');

// enable integrated search
$dg -> enable_search(true);

// set height and weight of datagrid
$dg -> set_dimension(800, 600);

// increase pagination size to 40 from default 20
$dg -> set_pagesize(40);
 
$dg -> display();

See Live Example!

Comments ( 0 )

Advanced Search

phpGrid also includes advanced search. By default, this feature is not enabled. To enable search use enable_advanced_search() method with parameter set to true. Once enabled, the advanced search can be toggled with the advanced search button on the footer.

The advanced search can search on multiple fields simultaneously with different comparison operators.

1
2
3
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->enable_advanced_search(true);
$dg -> display();

See Live Example!

Comments ( 0 )

Load Data with Vertical Scroll

In contrast to traditional pagination method to browse through data, you can use vertical scroll as alternative way to load data. It is done by set parameter in set_scroll() to true. When scroll position changes, phpGrid makes ajax call in the background and refresh the content in the grid. As a result, pagination is disabled automatically when this method is used.

Note that it does not load everything at once and only hold all the items from the start through to the latest point ever visited. This improves page loading time while prevents memory leaks from happening.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg->set_col_title("orderNumber", "Order No.");
$dg->set_col_title("orderDate", "Order Date");
$dg->set_col_title("shippedDate", "Shipped Date");
$dg->set_col_title("customerNumber", "Customer No.");
 
// hide a column
$dg -> set_col_hidden("requiredDate");

// change default caption
$dg -> set_caption("Orders List");

// set export type
$dg -> enable_export('EXCEL');

// enable integrated search
$dg -> enable_search(true);

// set height and weight of datagrid
$dg -> set_dimension(800, 600);

// increase pagination size to 40 from default 20
$dg -> set_pagesize(40);

// use vertical scroll to load data
$dg -> set_scroll(true);
 
$dg -> display();

See Live Example!

Comments ( 0 )

Theme Roller *

* Please note this feature is only available in paid versions.
** Premium Themes are now available to Enterprise and Universal Licenses customers

The overall look and feel of the phpGrid can be easily changed using set_theme() method. The theme elements are completely customizable through CSS. Theme files, css and images, are stored in css folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg->set_col_title("orderNumber", "Order No.");
$dg->set_col_title("orderDate", "Order Date");
$dg->set_col_title("shippedDate", "Shipped Date");
$dg->set_col_title("customerNumber", "Customer No.");
 
// hide a column
$dg -> set_col_hidden("requiredDate");

// change default caption
$dg -> set_caption("Orders List");

// set export type
$dg -> enable_export('EXCEL');

// enable integrated search
$dg -> enable_search(true);

// set height and weight of datagrid
$dg -> set_dimension(800, 600);

// increase pagination size to 40 from default 20
// $dg -> set_pagesize(40);

// use vertical scroll to load data
$dg -> set_scroll(true);

// change theme
$dg -> set_theme('dot-luv');
 
$dg -> display();

See Live Example!

Premium Themes are now available to Enterprise and Universal Licenses customers

  • Aristo
  • Cobalt
Comments ( 0 )

Display Hyperlink

You can display the text in column as static hyperlink by calling set_col_link() and passing the column name. Note this method only display static URL stored in database field. To display dynamic URL links based in variables, see the next example on set_col_dynalink() method.

Please note we are using Products table in this example.

1
2
3
4
5
6
7
8
9
$dg = new C_DataGrid("select * from products", "productCode", "productcode");
$dg -> set_col_title("productCode", "Product Code");
$dg -> set_col_title("productName", "Product Name");
$dg -> set_col_title("productLine", "Product Line");

// display static Url
$dg -> set_col_link("productUrl");                                            
                                                                                     
$dg -> display();

See Live Example!

Comments ( 0 )

Display Dynamic URL

From example above, we learn that phpGrid can display simple, static URL using set_col_link() method. However, it is often for database drive webpage that URL is dynamically formed based on parameters value. Method set_col_dynalink() is designed specially for this purpose.

The following demonstrates passing the column orderNumber as the dynamic value used as part of the URL.

1
2
3
4
5
6
7
8
9
10
11
12
$dg = new C_DataGrid("select * from products", "productCode", "productCode");
$dg -> set_col_title("productCode", "Product Code");
$dg -> set_col_title("productName", "Product Name");
$dg -> set_col_title("productLine", "Product Line");
         
// display static Url
$dg -> set_col_link("productUrl");
                 
// display dynamic url. e.g.http://www.example.com/?productCode=101&foo=bar
$dg -> set_col_dynalink("productCode", "http://www.example.com/", "productCode", '&foo=bar');                                                                  

$dg -> display();

See Live Example!

Comments ( 0 )

Data Format Display

phpGrid comes with several frequently used data formatter through set_col_format() method. Different data format has different format options. In most cases, users only need to set column formatting for “integer”, “number”, and “mail” using this method. For “currency’,”link”, and “showlink” formats, phpGrid provides a number of helper functions to make formatting simpler and easier. Refer to documentations on column formatter helper methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$dg = new C_DataGrid("select * from products", "productCode", "productCode");
$dg -> set_col_title("productCode", "Product Code");
$dg -> set_col_title("productName", "Product Name");
$dg -> set_col_title("productLine", "Product Line");

// display static Url
$dg -> set_col_link("productUrl");                                            

// dynamic url. e.g.http://www.example.com/?productCode=101&foo=bar
$dg -> set_col_dynalink("productCode", "http://www.example.com/", "productCode", '&foo=bar');

// column format
$dg -> set_col_currency("buyPrice");
$dg -> set_col_format("quantityInStock", "integer", array("thousandsSeparator" => ",",
                                                          "defaultValue" => "0"));  
$dg -> set_col_format("MSRP", 'currency', array("prefix" => "$",
                                                "suffix" => '',
                                                "thousandsSeparator" => ",",
                                                "decimalSeparator" => ".",
                                                "decimalPlaces" => '2',
                                                "defaultValue" => '0.00'));

// the above line is equivalent to the following helper function                        
$dg -> set_col_currency("MSRP", "$", '', ",",".", "2", "0.00");    
                                                                                   
$dg -> display();

See Live Example!

Didn’t see a formatter you need? You can also implement your own custom formatter such as phone number and SSN. Here’s a custom formatter sample code.

Comments ( 0 )

Image Display

image_display

Display image is easy in phpGrid. Simply set the column name in set_col_img(), phpGrid will take care of the rest.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$dg = new C_DataGrid("select * from products", "productCode", "productCode");
$dg -> set_col_title("productCode", "Product Code");
$dg -> set_col_title("productName", "Product Name");
$dg -> set_col_title("productLine", "Product Line");

// display static Url
$dg -> set_col_link("productUrl");                                            

// dynamic url. e.g.http://www.example.com/?productCode=101&foo=bar
$dg -> set_col_dynalink("productCode", "http://www.example.com/", "productCode", '&foo=bar');

// column format
$dg -> set_col_currency("buyPrice");
$dg -> set_col_format("quantityInStock", "integer", array("thousandsSeparator" => ",",
                                                          "defaultValue" => "0"));  
$dg -> set_col_format("MSRP", 'currency', array("prefix" => "$",
                                                "suffix" => '',
                                                "thousandsSeparator" => ",",
                                                "decimalSeparator" => ".",
                                                "decimalPlaces" => '2',
                                                "defaultValue" => '0.00'));

// the above line is equivalent to the following helper function                        
$dg -> set_col_currency("MSRP", "$", '', ",",".", "2", "0.00");                                      

// display image
$dg -> set_col_img("Image");
                                                 
$dg -> display();


You can also further adjust image display options such as width, height and border with CSS using set_col_property method. The CSS will only apply the specific column.

1
2
3
<style>
    .image_css img{width: 40pt;border:1px solid black;}
</style>
1
$dg->set_col_property('Image', array("classes"=>'image_css');

Alternatively, you resize images for the entire grid with CSS.

See Live Example!

Comments ( 0 )

Interactive Grid Resizing

When enabled, the small triangle icon is displayed at the right bottom corner of the php data grid. The grid can be resized by simply click and drag the icon using mouse. This is more convenient than setting the width and height in the code.

This function is currently in beta.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$dg= new C_DataGrid("select * from products", "productCode", "productCode");
$dg ->set_col_title("productCode", "Product Code");
$dg ->set_col_title("productName", "Product Name");
$dg ->set_col_title("productLine", "Product Line");

// display static Url
$dg ->set_col_link("productUrl");                                            

// dynamic url. e.g.http://www.example.com/?productCode=101&foo=bar
$dg -> set_col_dynalink("productCode", "http://www.example.com/", "productCode", '&foo=bar');

// column format
$dg -> set_col_currency("buyPrice");
$dg -> set_col_format("quantityInStock", "integer", array("thousandsSeparator" => ",",
                                                          "defaultValue" => "0"));  
$dg -> set_col_format("MSRP", 'currency', array("prefix" => "$",
                                                "suffix" => '',
                                                "thousandsSeparator" => ",",
                                                "decimalSeparator" => ".",
                                                "decimalPlaces" => '2',
                                                "defaultValue" => '0.00'));

// the above line is equivalent to the following helper function                        
$dg -> set_col_currency("MSRP", "$", '', ",",".", "2", "0.00");                                      

// display image
$dg -> set_col_img("Image");

// enable resize by dragging mouse
$dg -> enable_resize(true);
                                                 
$dg -> display();

See Live Example!

Comments ( 0 )

Editable Datagrid *

* Please note this feature is only available in paid versions.

The PHP datagrid is not editable by default. You can enable edit by simply calling enable_edit(). Currently, two types of edit modes are supported, FORM edit and INLINE. When Form edit mode is used, additional icons appear in the data grid footer for editing. When set to inline mode, the cells in the selected row become editable, and must press Enter key to save changes. Only a single row can be edited for either mode.

When edit is enabled in a grid, all of the CRUD operations, Create, Read, Update, and Delete, are supported by default. You can restrict types of edit operations permitted by specifying the second parameter in enable_edit(). For example, to disallow Delete, change it to $operations=’CRU’.

Please note save is disabled in the online demo for security reason.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber", "Customer No.");
 
// hide a column
$dg -> set_col_hidden("requiredDate");

// enable edit
$dg -> enable_edit("FORM", "CRUD");

$dg -> display();

See Live Example!

Update:
Beginning version 4.4, you can double click to edit whenever edit mode is enabled.
The toolbar can also be moved to top with a little javascript. See KB “Move Toolbar to Top of the Grid“.

Comments ( 0 )

Read only fields

Sometimes we don’t want certain fields to be editable, then we can use set_col_readonly() method.

Note that you can set more than one columns to be read only using this method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$dg = new C_DataGrid("SELECT * FROM Orders", "orderNumber", "Orders");

// change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber", "Customer No.");

// enable edit
$dg ->enable_edit("INLINE", "CRUD");
 
// hide a column
$dg -> set_col_hidden("requiredDate");

// read only columns, one or more columns delimited by comma
$dg -> set_col_readonly("orderDate, customerNumber");
 
$dg -> display();

Click on row to see the fields that are set to read only.

See Live Example!

Comments ( 0 )

Required fields

To set fields as required in an editable grid, use set_col_required() method. If required fields are left blank, an “* required” message will be displayed. One more more columns can be specified as required fields in this method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$dg = new C_DataGrid("SELECT * FROM Orders", "orderNumber", "Orders");

// change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber", "Customer No.");
 
// enable edit
$dg -> enable_edit("INLINE", "CRUD");

// hide a column
$dg -> set_col_hidden("requiredDate");

// read only columns, one or more columns delimited by comma
$dg -> set_col_readonly("orderDate, customerNumber");

// required fields
$dg -> set_col_required("orderNumber, customerNumber");
 
$dg -> display();

See Live Example!

To test, click on any row to toggle inline edit, leave a required fields blank, then hit Enter.

Comments ( 0 )

Select Multiple Records

You can select multiple records with set_multiselect() method. When multiselect is enabled, a checkbox is shown to the left of each row. It is currently designed to delete multiple records. More functionalities will be added to multiselect in the future.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$dg = new C_DataGrid("SELECT * FROM Orders", "orderNumber", "Orders");

// change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber", "Customer No.");
 
// enable edit
$dg -> enable_edit("INLINE", "CRUD");

// hide a column
$dg -> set_col_hidden("requiredDate");

// read only columns, one or more columns delimited by comma
$dg -> set_col_readonly("orderDate, customerNumber");

// required fields
$dg -> set_col_required("orderNumber, customerNumber");

// multiple select
$dg -> set_multiselect(true);
 
$dg -> display();

Optional JavaScript to retrieve selected rows

1
2
3
4
5
6
7
<script type="text/javascript">
function ShowSelectedRows(){
    var rows = getSelRows();
    // replace your own javascript here
    alert(rows);
}
</script>

To get value from a different cell of the select row:

1
$('#TABLE_NAME').jqGrid('getCell',row_id,'COLUMN NAME');

See Live Example!

Comments ( 0 )

Set Edit HTML Control

After enabling edit, you can set the type of HTML control with set_col_edittype() for any editable column used. List of Available controls are:

  • text
  • textarea
  • select
  • checkbox
  • password
  • autocomplete (version 6+) – New!

Text and textarea are set automatically based on the database access library ADOdb metatype as the default edit control.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$dg = new C_DataGrid("select * from employees", "employeeNumber", "Employees");
$dg -> set_col_title("employeeNumber", "Emp No.");
$dg -> set_col_title("lastName", "Last Name");
$dg -> set_col_title("firstName", "First Name");
$dg -> set_col_title("isActive", "Active?");
$dg -> set_col_format("email", "email");
$dg -> enable_edit("FORM", "CRUD");
$dg -> set_row_color("","","#DDEEF5");
$dg -> set_col_hidden('employeeNumber',false);

$dg -> set_col_edittype("isActive", "checkbox","1:0");
$dg -> set_col_edittype("reportsTo", "select", "Select employeeNumber, concat(firstName, ' ', lastName) from employees",false);
$dg -> set_col_edittype("officeCode", "autocomplete", "Select officeCode,city from offices",false);

// alternatively, for select type, you can hard-code the key value pair value
// $dg -> set_col_edittype("officeCode", "select", "1:San Francisco;2:Boston;3:NYC;4:Paris;5:Tokyo;6:Sydney;7:London");

$dg -> display();

See Live Example!

Comments ( 0 )

Master Detail Grid *

* Please note this feature is only available in paid versions.

The phpGrid went extra miles to make creating the master detail datagrid a super simple task. There is essentially a simple function to set_masterdetail() to set the master detail relationship between two datagrids, and have them work interactively.

The detail grid is a regular phpGrid object and can have the same methods like any other datagrid, such as description title, sort, and update etc. The detail grid renders dynamically based on the row selected in parent grid. A master grid can have one detail grid one or more detail datagrids.

Note that you can have master and detail grids from the same database table as long as different SQL alias are used.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$dg = new C_DataGrid("SELECT * FROM Orders", "orderNumber", "Orders");

// change column titles
$dg->set_col_title("orderNumber", "Order No.");
$dg->set_col_title("orderDate", "Order Date");
$dg->set_col_title("shippedDate", "Shipped Date");
$dg->set_col_title("customerNumber", "Customer No.");
 
// enable edit
$dg->enable_edit("INLINE", "CRUD");

// hide a column
$dg -> set_col_hidden("requiredDate");

// read only columns, one or more columns delimited by comma
$dg -> set_col_readonly("orderDate, customerNumber");

// required fields
$dg -> set_col_required("orderNumber, customerNumber");

// multiple select
$dg -> set_multiselect(true);
 
// second grid as detail grid. Notice it is just another regular phpGrid with properites.
$sdg = new C_DataGrid("SELECT orderNumber,productCode,quantityOrdered,priceEach FROM OrderDetails", "orderNumber", "OrderDetails");
$sdg->set_col_title("orderNumber", "Order No.");
$sdg->set_col_title("productCode", "Product Code");
$sdg->set_col_title("quantityOrdered", "Quantity");
$sdg->set_col_title("priceEach", "Unit Price");
$sdg->set_col_dynalink("productCode", "http://www.example.com/", "orderLineNumber", '&foo');
$sdg->set_col_format('orderNumber','integer', array('thousandsSeparator'=>'','defaultValue'=>''));
$sdg->set_col_currency('priceEach','$');

// define master detail relationship by passing the detail grid object as the first parameter, then the foriegn key name.
$dg->set_masterdetail($sdg, 'orderNumber');

$dg->display();

See Live Example!

Comments ( 0 )

Master Detail with Column Alias

It can be tricky working with master detail grids with column name alias, especially during edit. Using our sample database, here’s a working snippet.

1
2
3
4
5
6
7
8
$sg = new C_DataGrid("SELECT employeeNumber, employeeNumber as salesRepEmployeeNumber, lastName, firstName, email, jobTitle FROM  employees","employeeNumber","employees");
$sg_d1 = new C_DataGrid("SELECT customerNumber, customerName, city, state, salesRepEmployeeNumber, phone FROM customers","customerNumber","customers");

$sg->set_masterdetail($sg_d1, 'salesRepEmployeeNumber');
$sg->enable_edit()->set_col_readonly("salesRepEmployeeNumber");
$sg_d1->enable_edit();

$sg->display();

In master table “employeeNumber” is the FK reference to the detail table that has the column named “salesRepEmployeeNumber”. Create an alias that matches the corresponding name used in detail table, in this case it’s “salesRepEmployeeNumber”; it’s important to also keep the original column name because in some database such as MySQL does not allow alias in WHERE clause.

Lastly, use set_col_readonly() to set the alias name “salesRepEmployeeNumber” to read only so it won’t be passed to database for editing.

The only limitation is that the SQL alias must be in master grid, or the edit will again fail.

See Live Example!

Also available on KB: http://phpgrid.uservoice.com/knowledgebase/articles/411029

Comments ( 0 )

Subgrid

subgrid_ss

Defining a subgrid is essentially the same as setting up the master detail grid as described in our previous example. Again, only a single line of code change is required by calling set_subgrid().

Starting version 6, nested, drill-down subgrids are supported!

Important:
The difference between a master detail datagrid and a subgrid is that the subgrid displays inline grid rather than in a separate datagrid. In addition, it’s possible to nest master detail grids as well as subgrids. Nested subgrid currently is not yet supported.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// enable edit
$dg->enable_edit("INLINE", "CRUD");

// second grid as detail grid. Notice it is just another regular phpGrid with properites.
$sdg = new C_DataGrid("SELECT * FROM orderdetails", array("orderLineNumber", "productCode"), "orderdetails");
$sdg->enable_edit("INLINE", "CRUD");

// second grid as detail grid. Notice it is just another regular phpGrid with properites.
$sdg2 = new C_DataGrid("SELECT * FROM products", array("productCode"), "products");
$sdg2->enable_edit("INLINE", "CRUD");

// define master detail relationship by passing the detail grid object as the first parameter, then the foriegn key name.
$sdg->set_subgrid($sdg2, 'productCode');
$dg->set_subgrid($sdg, 'orderNumber');

$dg->display();

See 3-Level Nested Subgrid Example!

Comments ( 0 )

Multiple PHP Editable Datagrid

Did you know it is possible to have multiple editable grids in a single page? No need to separate your data management into multiple pages. You can now performa all your content administrative tasks in one page.

Note that you can have multiple datagrids of the same SQL table on a single page. However, you must give different SQL alias to each table.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$dg = new C_DataGrid("SELECT * FROM Orders", "orderNumber", 'Orders');
$dg->display();

$dg2 = new C_DataGrid("select * from employees", "employeeNumber", "Employees");
$dg2->display();

$dg3 = new C_DataGrid("select * from offices", "officeCode", "Offices");
$dg3->display();

$dg4 = new C_DataGrid("select * from productlines", "productLine", "ProductLines");
$dg4->display();

$dg5 = new C_DataGrid("select * from customers", "customerNumber", "Customers");
$dg5->display();

See Live Example!

Comments ( 0 )

Column Grouping with Summary *

* Please note this feature is only available in paid versions.

Simple Grouping with data-small

phpGrid can group data by columns. Simply define a column name on which grouping occur using method set_group_properties().

In addition to define grouping column, set summary field using method set_group_summary() by passing the column name and summary type, which can be sum, count, avg, min, or max.

1
2
3
4
5
6
7
$dg = new C_DataGrid("SELECT * FROM payments", "customerNumber", "orders");

$dg->set_group_properties('customerNumber');
$dg->set_group_summary('amount','sum');
$dg->set_group_summary('checkNumber','count');

$dg -> display();

See Live Example!

Comments ( 0 )

Master with Multiple Detail Grids *

* Please note this feature is only available in paid versions.

phpGrid supports a master grid with multiple detail grids. There is no limit on how many detail grids a master datagrid can have. Detail grids are defined the way as the master datagrid does. Click on example link to see it in action!

Note that you can have master and detail grids from the same database table as long as different SQL alias are used.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//suppliers master-detail
$sg = new C_DataGrid("SELECT * FROM suppliers","supplierCode","suppliers");
$sg->set_sql_key("supplierName");
 
//supplier detail 1: product lines
$sg_d1 = new C_DataGrid("SELECT * FROM supplierproductlines","supplierCode","supplierproductlines");
 
$sg->set_masterdetail($sg_d1, 'supplierName');
 
//supplier detail2: products
$sg_d2 = new C_DataGrid("SELECT productCode,productName,productDescription,quantityInStock,MSRP,productVendor FROM products","productCode","products");
 
//set detail 2 for suppliers
$sg->set_masterdetail($sg_d2, 'productVendor');
$sg->display();

See Live Example!

Comments ( 0 )

Nested Master Detail Datagrid *

* Please note this feature is only available in paid versions.

The master detail datagrid can be nested to show relationships for multilevel hierarchal data. The example shows only three levels, though the number of nested levels can be unlimited.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//suppliers master-detail
$sg = new C_DataGrid("SELECT * FROM suppliers","supplierCode","suppliers");
$sg->set_sql_key("supplierName");

//supplier detail2: products
$sg_d1 = new C_DataGrid("SELECT productCode,productName,productDescription,quantityInStock,MSRP,productVendor FROM products","productCode","products");

//nested grid-level 3 for products
$sg_d1_n1 = new C_DataGrid("SELECT * FROM productparts","productCode","productparts");

//set detail for products
$sg_d1->set_masterdetail($sg_d1_n1, 'productCode');

//set detail 2 for suppliers
$sg->set_masterdetail($sg_d1, 'productVendor');

$sg->display();

Note:
in example, click on #4 on suppliers, then S10_4698 in the first detail grid to reveal the third nested detail grid.
See Live Example!

Comments ( 0 )

Locale Setting

If you are using phpGrid in a language rather English, you may want the datagrid to display appropriate system text used by phpGrid such as “Submit”, “Next”, “Page”, “Find” etc. The language locale files are located in js\src\i18n directory.

1
2
3
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->set_locale('fr');        
$dg -> display();

See Live Example!

Comments ( 0 )

Reference to Multiple Databases *

* Please note this feature is only available in paid versions.

phpGrid nows supports data source from more than one database on a single page. Simply use the 4th parameter in constructor (C_DataGrid) to overwrite the initial database settings in conf.php.

In the following example, grid A binds a table from one database, while grid B binds another table from a completely different database, all on the same page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$gridA = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$gridA->enable_edit("INLINE","CRUD");
$gridA -> display();

// overwrite database settings with another database.
$gridB = new C_DataGrid("SELECT * FROM names", "id", "names",
                        array("hostname"=>"localhost",
                            "username"=>"USER2",
                            "password"=>"PASSWORD",
                            "dbname"=>"utf8db",
                            "dbtype"=>"mysql",
                            "dbcharset"=>"utf8"));

$gridB->enable_edit("INLINE","CRUD");
$gridB -> display();

See Live Example!

Comments ( 0 )

Display Non-English Characters

If database is created in charset other than default charset, e.g. “latin1″, some characters may be displayed as “?” in the grid. To properly display non-English characters, such as Spanish, Fresh, or Chinese, in MySQL, PostgreSQL, and Oracle you can define the character set value in ‘DB_CHARSET’ variable in conf.php.

In conf.php, set the DB_CHARSET to the corresponding charsets in your database.

version 6+ (with “PHPGRID_” prefix):

1
2
3
4
5
6
define('PHPGRID_DB_HOSTNAME','hostname'); // database host name
define('PHPGRID_DB_USERNAME', 'username'); // database user name
define('PHPGRID_DB_PASSWORD', 'password'); // database password
define('PHPGRID_DB_NAME', 'sampledb'); // database name
define('PHPGRID_DB_TYPE', 'mysql'); // database type
define('PHPGRID_DB_CHARSET','utf8'); // OPTIONAL. Leave blank to use the default charset

version 5.5.x and below:

1
2
3
4
5
6
define('DB_HOSTNAME','hostname'); // database host name
define('DB_USERNAME', 'username'); // database user name
define('DB_PASSWORD', 'password'); // database password
define('DB_NAME', 'sampledb'); // database name
define('DB_TYPE', 'mysql'); // database type
define('DB_CHARSET','utf8'); // OPTIONAL. Leave blank to use the default charset

Add the Meta element to the HTML head node and set character encoding to UTF-8. Note it’s important that the actual file must also be saved as UTF-8 encoding.

1
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

See Live Example!

Comments ( 0 )

In-cell Data Bar *

databar_ss

Bar chart is a great way to visualize numeric data. phpGrid now supports bar chart natively without 3rd party plugin using set_databar() method. You can have multiple data bar in a datagrid.

For complex data visualization, we recommend PHP Chart. Please visit PHP Chart for live demo.

1
2
3
4
5
6
7
8
9
10
11
12
$dg = new C_DataGrid("SELECT * FROM joborders", "jobNumber", "joborders");
$dg -> set_col_title("jobNumber", "Job Number");
$dg -> set_col_title("jobDescription", "Description");
$dg -> set_col_title("status", "Status");              
$dg -> set_col_title("percentComplete", "Progress (%)");
$dg -> set_col_title("isClosed", "Closed");
 
$dg -> set_databar("percentComplete","blue");
$dg -> set_databar("jobNumber","blue");
$dg -> enable_edit("INLINE", "CRUD");
 
$dg -> display();

See Live Example!

Comments ( 0 )

Conditional Value *

* Please note this feature is not available in Lite and Basic versions.

Conditional Value is similar to conditional format (see set_conditional_format but with simplier set of features. Use set_conditional_value() to dynamically display a value when specific condition is met. The conditional value can be text, HTML, or even CSS style.

You can use conditional value with data bar in the same grid.

1
2
3
4
5
6
7
8
.tstyle
{
display:block;background-image:none;margin-right:-2px;margin-left:-2px;height:14px;padding:5px;background-color:green;color:navy;font-weight:bold
}
.fstyle
{
display:block;background-image:none;margin-right:-2px;margin-left:-2px;height:14px;padding:5px;background-color:yellow;color:navy
}

PHP Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$dg = new C_DataGrid("SELECT * FROM joborders", "jobNumber", "joborders");
$dg -> set_col_title("jobNumber", "Job Number");
$dg -> set_col_title("jobDescription", "Description");
$dg -> set_col_title("status", "Status");              
$dg -> set_col_title("percentComplete", "Progress (%)");
$dg -> set_col_title("isClosed", "Closed");
 
$dg->set_conditional_value("isClosed", "==1", array(
    "TCellValue"=>"<img src='SampleImages/checked.gif' />",
    "FCellValue"=>"<img src='SampleImages/unchecked.gif' />"));
 
$dg->set_conditional_value("status", "=='Complete'", array(
    "TCellStyle"=>"tstyle",
    "FCellStyle"=>"fstyle"));
 
$dg->enable_edit('INLINE', 'CRUD');
 
$dg->set_multiselect(true);
$dg -> set_databar("percentComplete","red");
$dg -> display();

See Live Example!

Note:
For even more complex conditions, please refer to row level permission example by using set_grid_property() and add_event() method.

Comments ( 0 )

Create Excel-Like Grid

Use enable_autowidth() and enable_autoheight() to set datagrid width as the same as the current page dimension to fill the entire screen, similar to what Excel spreadsheet looks like.

1
2
3
4
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->enable_edit('FORM', 'CRUD');
$dg->enable_autowidth(true)->enable_autoheight(true);
$dg -> display();

See Live Example!

Hint:
Call enable_kb_nav() method to move between rows using only keyboard.

Comments ( 0 )

Horizontal Scroll

Set parameter $shrinkToFit in set_dimension() to false to enable horizontal scroll when the container width is less than the grid width. The scroll bar will not show when the grid width is equal or less than the container width.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
 // change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber",  "Customer No.");
// hide a column
$dg -> set_col_hidden("requiredDate");
// change default caption
$dg -> set_caption("Orders List");
// set export type
$dg -> enable_export('EXCEL');
 // enable integrated search
$dg -> enable_search(true);
// set height and weight of datagrid
$dg -> set_dimension(800, 600, false);
// increase pagination size to 40 from default 20
$dg -> set_pagesize(40);

$dg -> display();

See Live Example!

Comments ( 0 )

Conditional Format *

* Please note this feature is not available in Lite and Basic versions.

conditional_format_ss

Conditional formatting example using set_conditional_format() method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

//Format a cell based on the specified condition
$dg->set_conditional_format("orderNumber","CELL",array(
    "condition"=>"eq","value"=>"10107","css"=> array("color"=>"#ffffff","background-color"=>"green")));

$dg->set_conditional_format("customerNumber","CELL",array(
    "condition"=>"eq","value"=>"141","css"=> array("color"=>"red","background-color"=>"#DCDCDC")));

// Format a row based on the specified condition
$dg->set_conditional_format("comments","ROW",array(
    "condition"=>"cn","value"=>"request","css"=> array("color"=>"white","background-color"=>"#4297D7")));    
                     
$dg->set_multiselect(true);
$dg -> display();

See Live Example!

Note:
For even more complex conditions, please refer to row level permission example by using set_grid_property() and add_event() method.

Comments ( 0 )

Method Chaining

Method chaining is now supported starting version 5.0. It’s not required, but it provides more readable code and reduce amount of source code in a fluent interface.

For example:

With method chaining (v5.0 and later):

1
2
$dg->set_col_title(“lastName”, “Last Name”)->set_col_required(“lastName”, true)->set_co_default(“lastName”, “Robert”);
$dg->enable_edit(“FORM”)->enable_export(true)->enable_resize(true);

Without method chaining:

1
2
3
4
5
6
$dg -> set_col_title(“lastName”, “Last Name”);
$dg -> set_col_required(“lastName”, true);
$dg -> set_co_default(“lastName”, “Robert”);
$dg -> enable_edit(“FORM”);
$dg -> enable_export(true);
$dg -> enable_resize(true);
Comments ( 0 )

Custom Event Handler

phpGrid supports custom event handler using add_event() method. The event handlers are essentially JavaScript functions so they must be enclosed with PHP heredoc syntax. This is a very powerful function once you are familiar with events.

Below are the events used in this example:

  • jqGridSelectRow
  • jqGridrowattr
  • jqGridAddEditAfterSubmit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

$onSelectRow = <<<ONSELECTROW
function(status, rowid)
{
    alert('event 1');
    console.log(rowid);
    console.log(status);
   
    /* example to redirect a new URL when select a row */
    // orderNumber = $('#orders').jqGrid('getCell',rowid,'orderNumber');
    // customerNumber = $('#orders').jqGrid('getCell',rowid,'customerNumber');
    // window.location = encodeURI("http://example.com/" + "?" + "orderNumber=" + orderNumber + "&customerNumber="+customerNumber);
}
ONSELECTROW
;

$onSelectRow2 = <<<ONSELECTROW2
function(status, rowid)
{
    alert('event 2');
    console.log("here");
}
ONSELECTROW2
;

$rowattr = <<<ROWATTR
function (rowData, inputRowData)
{
    return rowData.status === "OnHold" ? {style: "background-color:blue"} : {};
}
ROWATTR
;

// post data another page after submit
$afterSubmit = <<<AFTERSUBMIT
function (event, status, postData)
{
    console.log(postData);
    alert(postData.customerNumber);
    $.ajax({ url: '/my/site',
        data: {custNum: postData.customerNumber}, // replace customerNumber with your own field name
        type: 'post',
        success: function(output) {
                    alert(output);
                }
        });
}
AFTERSUBMIT
;

$dg->add_event("jqGridSelectRow", $onSelectRow);
$dg->add_event("jqGridSelectRow", $onSelectRow2);
$dg->add_event("jqGridrowattr", $rowattr);
$dg->add_event("jqGridAddEditAfterSubmit", $afterSubmit);
$dg->enable_edit('FORM');
$dg -> display();

See Live Example! (click on any row to trigger event)

Comments ( 0 )

Column Property

You can now directly manipulate individual column properties without using helper set_col_* functions such as set_col_format() and set_col_readonly() .  This is suitable for users who are already familiar with jqGrid colMdel API (http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options).

The new column property method does not replace existing helper functions. It should be used beside by side with the existing set_col_* helper functions.

1
2
3
4
5
6
7
8
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg -> set_row_color('yellow', 'blue', 'lightgray');
$dg -> set_col_property("orderNumber", array("name"=>;"Order Number", "width"=>;40));
// display only time
$dg -> set_col_property("orderDate",
                        array("formatter"=>;"date",
                              "formatoptions"=>;array("srcformat"=>;"ISO8601Short","newformat"=>;"g:i A"));
$dg -> display();

See Live Example!

Comments ( 0 )

Hyperlink to Call JavaScript Function

You can show hyperlink using set_col_link for static link or set_col_dynalink for dynamic link. What about if you want to do something even fancier, like open a new window, or trigger a JavaScript event when hyperlink is clicked?

To call JavaScript function on hyperlink click, use “showlink” in set_col_format method.

In the following example, the first set_col_format displays text in alert window using JavaScript function “myFunction” to retrieved text from a different cell in the same row. The second does a phpgrid.com site search using jQuery Ajax function “phpGridSiteAjaxSearch”, and displays the result in a alert message window.

PHP:

1
2
3
4
5
6
7
8
9
10
11
12
13
$dg = new C_DataGrid("select * from products", "productCode", "products");
$dg -> set_col_title("productCode", "Product Code");
$dg -> set_col_title("productName", "Product Name");
$dg -> set_col_title("productLine", "Product Line");

$dg->set_col_format("productLine", "showlink", array("baseLinkUrl"=>"javascript:", "target"=>"_self",
    "showAction"=>"myFunction(jQuery('#products'),'",
    "addParam"=>"');"));                                                                                                                          

$dg->set_col_format("productName", "showlink", array("baseLinkUrl"=>"javascript:", "target"=>"_self",
    "showAction"=>"phpGridSiteAjaxSearch(jQuery('#products'),'",
    "addParam"=>"');"));                                                                                                                          
$dg -> display();

JavaScript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
myFunction = function (grid,param) {
    var ar = param.split('=');
    if (grid.length > 0 && ar.length === 2 && ar[0] === '?id') {
        var rowid = ar[1];
        var prodDesc = grid.getCell(rowid, 'productDescription');

        alert(prodDesc);
    }
};

phpGridSiteAjaxSearch = function (grid,param) {
    var ar = param.split('=');
    if (grid.length > 0 && ar.length === 2 && ar[0] === '?id') {
        var rowid = ar[1];
        var productName = grid.getCell(rowid, 'productName');

        jQuery.ajax({
            url: 'http://phpgrid.com',
            data: { s: productName },
            type: 'GET',
            dataType: 'text',
            success:function(data,status) {
                // your code goes here for a successul Ajax call .e.g open a new window
                alert(data);
            },
            error:function(data,status,err){
                alert(data + status);
            }
        });
    }
};

See Live Example

Comments ( 0 )

PHP Datagrid AJAX File Upload

* The file upload is supported in Enterprise and Universal license.

File upload is one of the most requested features. And we are finally able to delivery this new feature. It requires only a SINGLE LINE of code, with only a single function call to set_col_fileupload(). Since PHP is installed as Apache module in our host server, the 3rd parameter is optional that the physical path is automatically mapped based on 2nd parameter, the base URL.

All the file operations (Update, Delete) are Ajax-based, without refreshing the page.

1
2
3
4
5
$dg = new C_DataGrid("SELECT * FROM shippers", "ShipperID", "shippers");
$dg -> set_col_fileupload("fileToUpload", '/phpGridx/photos/');
$dg -> enable_edit('FORM');
$dg->set_col_img("fileToUpload", "/phpGridx/photos/");
$dg -> display();

You should consider resizing images displayed so large images won’t blow your datagrid out of proportion. Read more about Image resize using CSS.

The below screenshot (click to enlarge) illustrates the file edit operations in edit form. It has the “delete” button to remove the existing file before uploading a new one. The file name is saved to table “shippers”.

The below screenshot (click to enlarge) shows uploading new file as part of creating a new record by click on “choose file”, then pick file “truck.jpg” from the local system. Then the file “truck.jpg” is saved to file system under “/phpGridx/foo/” folder, and the file name is stored in table “shippers” alone with rest of data.

The follow screen (click to enlarge) shows that new record has been successfully created and the file “truck.jpg” has been successfully uploaded.

Comments ( 0 )

Customize Edit Form Layout

By default, the edit form is displayed a single column table. This is fine for table with small numbers of fields. When you got a large number of fields, the chances are that you want to modify the layout to display multiple columns. Use formoptions property “rowpos” and “colpos” for this purpose.

The following example demonstrates a 2-column edit form.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber", "Customer No.");

// hide a column
$dg -> set_col_hidden("requiredDate");

// enable edit
$dg -> enable_edit("FORM", "CRUD");

$dg -> set_col_property("orderNumber", array("formoptions"=>array("rowpos"=>1,"colpos"=>1)));
$dg -> set_col_property("orderDate", array("formoptions"=>array("rowpos"=>1,"colpos"=>2)));
$dg -> set_col_property("requiredDate", array("formoptions"=>array("rowpos"=>2,"colpos"=>1)));
$dg -> set_col_property("shippedDate", array("formoptions"=>array("rowpos"=>2,"colpos"=>2)));
$dg -> set_col_property("status", array("formoptions"=>array("rowpos"=>3,"colpos"=>1)));
$dg -> set_col_property("customerNumber", array("formoptions"=>array("rowpos"=>3,"colpos"=>2)));
$dg -> set_col_property("comments", array("formoptions"=>array("rowpos"=>4,"colpos"=>1)));

$dg->set_form_dimension(580, 270);

$dg->enable_debug(false);
$dg -> display();

Form Layout Screenshot

Hint: the edit form is resizable by click and drag bottom-right corner using mouse.

custom form edit layout

See Live Example! (double click a row to see 2-column edit form)

Comments ( 0 )

phpGrid, phpChart Integration

 

Run Demo

phpGrid phpChart Integration

It’s easy to combine both phpGrid and phpChart into a seamless integrated, interactive, and completely web-based ad-hoc content and report management tool.

 

Setup

Before start, You must acquire both phpGrid and phpChart. You can download both for free.

It’s important to install phpGrid and phpChart in separate folder. Below is the folder structure used in our example. phpGrid and phpChart each resides in separate folder inside phpGrid_phpChart folder under web root folder htdocs. This is RECOMMENDED folder hierarchy.

htdocs
+-- phpGrid_phpChart
|   |-- phpGrid
|   |   +-- conf.php
|   |-- phpChart
|   |   +-- conf.php
|   +-- phpgrid_phpchart_integration.php
 

Once folder structure is ready. Set up phpGrid SERVER_ROOT value and phpChart SCRIPTPATH value in each of their respective conf.php file.

phpGrid conf.php

1
define('SERVER_ROOT', '/phpGrid_phpChart/phpGrid');

phpChart conf.php

1
define('SCRIPTPATH','/phpGrid_phpChart/phpChart/');
 

Programming

Now, we can move on to the actual integration. First all, include both conf.php files on top of the script.

1
2
require_once("phpGrid/conf.php");
require_once("phpChart/conf.php");

Then, create the chart with phpChart. Here in this example we have two charts. The first chart has a single series of data. The second one has two series and renders bar chart instead of the default line chart. All the phpChart methods and properties documents are available on phpChart.net. Pass “null” as the series data if you don’t want to have any initial data in the chart.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// first phpChart with one series
$pc = new C_PhpChartX(array(array(null)), 'Graph');
$pc->set_axes(array(
        'xaxis'=> array('label'=>'Buy Price'),
        'yaxis'=> array('label'=>'$')
    ));
$pc->draw(800,500);

// second phpChart with two series
$pc2 = new C_PhpChartX(array(array(null), array(null)), 'Graph2');
$pc2->set_axes(array(
        'xaxis'=> array(
            'label'=>'Buy Price/MSRP (by Product Code)'),
        'yaxis'=> array('label'=>'$')
    ));
$pc2->set_animate(true);
$pc2->set_legend(array('show'=>true,'location'=>'nw'));
$pc2->draw(800,500);

Finally the last part is to code the datagrid. In our example, we use “products” database table. The most important part of the datagrid is the custom event handler “jqGridLoadComplete” in which the phpGrid, phpChart integration happens. Here, values in both “buyPrice” and “MSRP” columns are retrieved and stored in d1 and d2 as array. You can replace those columns with columns with your own choice in your table. GraphData1 and GraphData2 are used to store the series of data that later will be used to plot our charts created earlier.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$dg = new C_DataGrid("SELECT * FROM products", "productCode", "products");
$dg->enable_edit('FORM');
$onGridLoadComplete = <<<ONGRIDLOADCOMPLETE
function(status, rowid)
{
    var GraphData1 = [];
    var GraphData2 = [];

    d1 = $('#products').jqGrid('getCol', 'buyPrice', false);
    d2 = $('#products').jqGrid('getCol', 'MSRP', false);
    npoints = d1.length;
    for(var i=0; i < npoints; i++){
        GraphData1[i] = [i+1, parseInt(d1[i])];
    }
    _Graph.series[0].data = GraphData1;
    _Graph.replot({resetAxes:true});

    for(var i=0; i < npoints; i++){
        GraphData1[i] = [i+1, parseInt(d1[i])];
        GraphData2[i] = [i+1, parseInt(d2[i])];
    }
    _Graph2.series[0].data = GraphData1;
    _Graph2.series[1].data = GraphData2;
    _Graph2.replot({resetAxes:true});
}
ONGRIDLOADCOMPLETE
;
$dg->add_event("jqGridLoadComplete", $onGridLoadComplete);
$dg->set_col_property('MSRP', array('classes'=>'msrp_bg'));   // change column background color
$dg->set_col_property('buyPrice', array('classes'=>'buyprice_bg'));  // change column background color
$dg->enable_search(true);
$dg->display();

To easily recognize the data source, we set the datagrid column background color to match the series color in phpChart using CSS class

1
2
.msrp_bg { background-color: #4BB2C5 !important; }
.buyprice_bg {  background-color: #F8C05B !important; }
 

The COMPLETE example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php
require_once("phpGrid/conf.php");
require_once("phpChart/conf.php");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>phpGrid phpChart Integration Example</title>
</head>
<body>
<STYLE>
.msrp_bg {
    background-color: #4BB2C5 !important;
}
.buyprice_bg {
    background-color: #F8C05B !important;
}
</STYLE>

<p>Try do a quick search or do a sort. Observe the graph updates in real-time.</p>

<table><tr><td>
<?php
// first phpChart with one series
$pc = new C_PhpChartX(array(array(null)), 'Graph');
$pc->set_axes(array(
        'xaxis'=> array('label'=>'Buy Price'),
        'yaxis'=> array('label'=>'$')
    ));
$pc->draw(600,300);
?>
</td>
<td>
<?php
// second phpChart with two series
$pc2 = new C_PhpChartX(array(array(null), array(null)), 'Graph2');
$pc2->set_axes(array(
        'xaxis'=> array(
            'label'=>'Buy Price/MSRP (by Product Code)'),
        'yaxis'=> array('label'=>'$')
    ));
$pc2->set_animate(true);
$pc2->set_legend(array('show'=>true,'location'=>'nw'));
$pc2->draw(600,300);
?>
</td></tr></table>

<?php
$dg = new C_DataGrid("SELECT * FROM products", "productCode", "products");
$dg->enable_edit('FORM');

$onGridLoadComplete = <<<ONGRIDLOADCOMPLETE
function(status, rowid)
{
    var GraphData1 = [];
    var GraphData2 = [];

    d1 = $('#products').jqGrid('getCol', 'buyPrice', false);
    d2 = $('#products').jqGrid('getCol', 'MSRP', false);
    npoints = d1.length;
    for(var i=0; i < npoints; i++){
        GraphData1[i] = [i+1, parseInt(d1[i])];
    }
    _Graph.series[0].data = GraphData1;
    _Graph.replot({resetAxes:true});

    for(var i=0; i < npoints; i++){
            GraphData1[i] = [i+1, parseInt(d1[i])];
            GraphData2[i] = [i+1, parseInt(d2[i])];
    }
    _Graph2.series[0].data = GraphData1;
    _Graph2.series[1].data = GraphData2;
    _Graph2.replot({resetAxes:true});
}
ONGRIDLOADCOMPLETE
;

$dg->add_event("jqGridLoadComplete", $onGridLoadComplete);
$dg->set_col_property('MSRP', array('classes'=>'msrp_bg'));
$dg->set_col_property('buyPrice', array('classes'=>'buyprice_bg'));
$dg->enable_search(true);
$dg->display();
?>
</body>
</html>

That’s it! Do a quick search or sort. Observe the graph updating in real-time.

Give it a try! | Download Integration Example File

Technical Notes

  • The Javascript used in the custom event handler in phpGrid is the bread and butter of integration.
  • Set array to null for initial graph.
  • On initial plot creation you can pass series of data in a 1-D array. jqPlot internally converts it to a 2-D array. However, this doesn’t happen on .replot().
  • If the page throws an error
    1
    Notice: Constant DEBUG already defined in /phpGrid/conf.php on line 2

    This is because both phpChart and phpGrid have DEBUG constant, you need to comment out of them in conf.php

    1
    // define('DEBUG', true);
Comments ( 0 )

Virtual/Calculated Column

Starting version 5.5, you can now add virtual column, AKA calculated column, to your existing datagrid. Virtual, by definition, is that it doesn’t exist in the database table. It’s a calculated field created from other columns. The virtual columns are added to the END of the existing datagrid.

phpGrid only adds a “virtual” column and does NOT change the database table structure. Front-end user should not be able to add/change a column in your database table structure. It should be done only by a very smaller number of people such as DBA, and ultimately through a back-end database administration program.

It’s important that the virtual column name is NOT one of the existing database column names used in PHP datagrid.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->enable_edit('INLINE');

// calculated value to be displayed in the virtual column
// n1 stores column 1 value, n2 stores column 7 value..and so on.
$col_formatter = <<<COLFORMATTER
function(cellvalue, options, rowObject){
    var n1 = parseInt(rowObject[0],10),      
        n2 = parseInt(rowObject[6],10);      
    return n1+n2;
}
COLFORMATTER;

$dg -> add_column(
        'total',
        array('name'=>'total',
            'index'=>'total',
            'width'=>'360',
            'align'=>'right',
            'sortable'=>false,
            'formatter'=>$col_formatter),
        'Total (Virtual)');
$dg->display();

See Live Example! (The last column “Total” is a virtual column)

Comments ( 0 )

Custom Data Validation

phpGrid automatically does data validation based on database data type such as a string cannot be used when the data type is integer and non-null field must have a value. It’s sufficient in most everyday use cases.

Client Side Validation

Starting version 5.5, users can use their own validation javascript function for more complex data edit rules. Use set_col_customrule() method is created for this purpose. Below is an example of three Javascript functions used for custom validation. You can even compare data among multiple columns. The Javascript functions in example is rather over simplified, but you get the picture. Once obtained the cell value, you can develop even more complex Javascript function to validation your data.

Server Side Validation

For server side data validation, in your javascript function, use jQuery.ajax to call your server side validation routine. An example of Ajax call can be found on Hyperlink to Call JavaScript Function example

Make sure that you play around with the live example after the code snippet!

Javascript Functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// validation (FORM and INLINE)
function price_validation1(value, colname) {
    if(value < 0){
       return [false,colname + " must be zero a positive integer."];
    }
    return [true, ""];
}

// validation (INLINE only). Note the technique to obtain a specific cell value
function price_validation2(value, colname) {
    var rowId = jQuery("#products").jqGrid('getGridParam','selrow');
    if(parseFloat(jQuery('#' + rowId + '_' + 'buyPrice').val()) >  parseFloat(jQuery('#' + rowId + '_' + 'MSRP').val()))
        return [false,"buyPrice must be equal or less than MSRP."];
    else
        return [true,""];
}

// validation (FORM only). Note the technique to obtain a specific cell value is different from INLINE edit.
function price_validation3(value, colname) {
    if(parseFloat(jQuery('#buyPrice').val()) >  parseFloat(jQuery('#MSRP').val()))
        return [false,"buyPrice must be equal or less than MSRP."];
    else
        return [true,""];
}

PHP

1
2
3
4
5
$dg = new C_DataGrid("SELECT * FROM products", "productCode", "products");
$dg->enable_edit('FORM');
$dg->set_col_customrule('quantityInStock', 'price_validation1');
$dg->set_col_customrule('buyPrice', 'price_validation3');
$dg->display();

See Live Example! (Try set quantityInStock to a negative number, and buyPrice < MSRP.)

Comments ( 0 )

Local Array Data Source

phpGrid now supports local array data source (version 5.5+). No database is required for local data. So it’s NOT necessary to define PHPGRID_DB_* variables in conf.php when using local array. Simply pass a PHP array as the first parameter to the phpGrid constructor. Everything else is virtually the same.

In the below example, the first segment creates a local PHP array, namely $data1, will be used as the data source for phpGrid. The second segment demonstrates passing the $data1 to the phpGrid constructor and call its methods. All existing phpGrid methods can be used the same way as a database-driven datagrid*.

Make sure to check out the live example!

Local Array (PHP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$name = array('Bonado', 'Sponge', 'Decker', 'Snob', 'Kocoboo');
for ($i = 0; $i < 200; $i++)
{
    $data1[$i]['id']    = $i+1;
    $data1[$i]['foo']    = md5(rand(0, 10000));
    $data1[$i]['bar1']    = 'bar'.($i+1);
    $data1[$i]['bar2']    = 'bar'.($i+1);
    $data1[$i]['cost']    = rand(0, 100);
    $data1[$i]['name']    = $name[rand(0, 4)];
    $data1[$i]['quantity'] = rand(0, 100);
    $data1[$i]['discontinued'] = rand(0, 1);
    $data1[$i]['email'] = 'grid_'. rand(0, 100) .'@example.com';
    $data1[$i]['notes'] = '';
}

phpGrid Code ($data1 is the local array created above)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$dg = new C_DataGrid($data1, "id", "data1");   // $data1 is the local array
$dg->set_col_title("id", "ID")->set_col_width('id', 20);
$dg->set_col_title("foo", "Foo");
$dg->set_col_title("bar", "Bar");
$dg->set_col_title('discontinued', 'disc.')
    ->set_col_width('discontinued', 35);
$dg->set_col_align('cost', 'right')
    ->set_col_currency('cost', '$');
$dg->set_col_width('bar1', 40);
$dg->set_col_width('quantity', 220);
$dg->set_row_color('lightblue', 'yellow', 'lightgray');
$dg->set_databar('quantity', 'blue');
$dg->enable_search(true);
$dg->enable_edit('FORM', 'CRUD');
$dg->enable_resize(true);
$dg->set_col_format('email', 'email');
$dg->set_col_dynalink('name', 'http://example.com', array("id", "name"));
$dg->set_caption('Array Data Test');
$dg->set_col_hidden('bar2');
$dg->set_col_property('notes', array('edittype'=>'textarea','editoptions'=>array('cols'=>40,'rows'=>10)))
    ->set_col_wysiwyg('notes');
$dg->set_dimension(900, 400);
//$dg->set_multiselect(true);
$dg->set_conditional_value('discontinued', '==1',  array("TCellStyle"=>"tstyle"));
$dg->set_theme($theme_name);
$dg->display();

Screenshot

local_array

* Please note that master detail, subgrid, export and file uploads are not yet available when using local array data source.

** Local array data source currently is only available to Enterprise and Universal Licensees.

See Live Example!

JSON Data Source

It’s also possible to use JSON string as a data source with one extra step: use json_decode and set the second parameter to true to return the decoded JSON string to an associative array.

Once you have the array, it can be passed to the phpGrid constructor as if it’s a local array data source. This is useful when your data is real-time or loaded from a remote source such as stock quote and RSS etc.

1
2
3
4
5
6
$url = "http://myurl.com/json_string";
$json = file_get_contents($url);
$json_output = json_decode($json, true);

$dg = new C_DataGrid($json_output['items'], "id", "items");
$dg->display();
Comments ( 0 )

Column Freeze

You can now use set_col_frozen method to set column freeze method. It’s useful when working with a big table with many columns. The freezing column must start from the very left and then one by one to the right.

1
2
3
4
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->set_dimension(600, 400, false);
$dg->set_col_frozen('orderNumber');
$dg -> display();

Note that it is recommended to set text not to wrap with CSS “nowrap”. See http://phpgrid.uservoice.com/knowledgebase/articles/154972

See Live Example!

Comments ( 0 )

Column Methods

Version 5.5.5 introduced set_grid_method() method. You can use this method to call any jqGrid javascript method that can perform actions on the grid as a whole. However, it’s not possible to manipulate the grid on a row or cell level using set_grid_method.

The example below demonstrates set_grid_method to grouping header by calling the jqGrid “setGroupHeader” method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$dg = new C_DataGrid("SELECT * FROM payments", "customerNumber", "orders");

$dg->set_col_width("customerNumber", 30);
$dg->set_col_width("checkNumber",50);
$dg->set_col_width("amount",50);

$dg->set_grid_method('setGroupHeaders', array(
                                array('useColSpanStyle'=>true),
                                'groupHeaders'=>array(
                                        array('startColumnName'=>'customerNumber',
                                              'numberOfColumns'=>2,
                                              'titleText'=>'Numbers Header') )));

$dg -> display();

See Live Example!

Comments ( 0 )

Inline Edit Actions Column

Inline edit mode also comes with actions column with edit and delete buttons. Use add_column method to add “actions”. In formatoptions, specify the following property to display or hide edit and delete buttons:

  • delbutton – true or false
  • editbutton – true or false

Note that when use actions column, it is not necessary to specify edit options in enable_edit method. An advantage using actions column is that it’s possible to have row-level permission. Please see datagrid row-level edit permission example.

1
2
3
4
5
6
7
8
9
10
11
12
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

// enable edit - but no need to specify 2nd parameter because we will be using actions column
$dg -> enable_edit("INLINE");

$dg->add_column("actions", array('name'=>'actions',
    'index'=>'actions',
    'width'=>'70',
    'formatter'=>'actions',
    'formatoptions'=>array('keys'=>true, 'editbutton'=>true, 'delbutton'=>false)),'Actions');

$dg -> display();

See Live Example!

Comments ( 0 )

Row-level Edit Permission

Using actions column in the earlier example, it’s now possible to specify row-level permission for editing using additional javascript.

The Javascript used here hides the delete and edit buttons based condition that when status equals to “Shipped”. The example shown is for demo purpose only. It’s NOT 100% secure. Programmer should still validate the permission on the server side.

For simpler condition without using Javascript, you can consider set_edit_condition() method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// note this should not replace database role-based or user-based permissions.
$onGridLoadComplete = <<<ONGRIDLOADCOMPLETE
function(status, rowid)
{
    var ids = jQuery("#orders").jqGrid('getDataIDs');
    for (var i = 0; i < ids.length; i++)
    {
        var rowId = ids[i];
        var rowData = jQuery('#orders').jqGrid ('getRowData', rowId);

        if($("#orders").jqGrid("getCell", rowId, "status") == "Shipped"){
            $("#orders").jqGrid("setCell", rowId, "actions", " zzz ", {"display":"none"}); // not possible to set value for virtual column
        }
    }
}
ONGRIDLOADCOMPLETE
;

$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->set_col_hidden('comments');

$dg->add_column("actions", array('name'=>'actions',
    'index'=>'actions',
    'width'=>'80',
    'formatter'=>'actions',
    'formatoptions'=>array('keys'=>true)),'Actions');
$dg->set_grid_property(array('onSelectRow'=>'')); // remove onSelect event
$dg->add_event("jqGridLoadComplete", $onGridLoadComplete);
$dg->enable_edit('INLINE');

$dg -> display();

See Live Example!

Comments ( 0 )

Multiple Datagrid Instances From the Same Table

You can certain have more than one datagrid instances from the same database table. Just make sure to give each unique name using set_jq_gridName() method.

1
2
3
4
5
6
7
8
9
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->enable_edit();
$dg -> display();

$dg2 = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg2->set_jq_gridName('order2');
$dg2->set_caption("order 2");
$dg2->enable_edit();
$dg2 -> display();

See Live Example! (scroll to the right view the 2nd grid)

Comments ( 0 )

Column Chooser & Sortable Row

The example below demonstrates column chooser and sortable row features. Click on the column chooser icon in the footbar to reveal the column chooser dialog. To test sortable row, drag a row and move it around.

1
2
3
4
5
6
$dg = new C_DataGrid("select * from products", "productCode", "products");

$dg -> enable_columnchooser(true);
$dg -> set_sortablerow(true);

$dg -> display();

See Live Example!

Comments ( 0 )

Composite Primary Key Support *

* An exclusive feature for phpGrid Enterprise and Universal License

In the past, phpGrid supports database SQL that only has a single primary key. If multiple primary keys exist, the recommended workaround was to create an auto-increment column as an alternative single primary key.

Though most cases the above solution is sufficient, as the database grows and its structure evolves, the need to support composite primary key becomes essential, especially in an enterprise environment.

Starting phpGrid 6 (Enterprise & Universal only), you can pass an array of string as the primary key as the $sql_key in data grid constructor. e.g.

1
array("KEY1", "KEY2", "KEY3"...);
 

Lots of resources devoted into developing this important feature while making it simple at the same time. In stead of passing a single string variable in the constructor as the primary key, you can now pass an array of strings as the composite primary key. For a single primary key, you can still use a string or an array with a single string value. e.g.

Complete composite primary key example:

1
2
3
$dg = new C_DataGrid("SELECT * FROM orderdetails", array("productCode", "orderNumber"), "orderdetails");
$dg->enable_edit("FORM", "CRUD");
$dg->display();

See Live Example!

For single primary key, you can still pass it as string type, or an array with just a single string element.

1
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");

- OR -

1
$dg = new C_DataGrid("SELECT * FROM orders", array("orderNumber"), "orders");
Comments ( 0 )