Advanced Ext-Js Grid with JSON Data and Cell Actions
In my basic grid example, Data was loaded within the javascript call. This post contains an advanced demonstration of using AJAX/JSON to load data remotely for better performance. You will notice that the web page rendered quickly and proceeds before loading the data remotely.
To make use of the fields and columns more efficiently and accurately. I’ve used PHP arrays to construct them as I want to.
global $attribute_code;
$attribute_code = array(
array('code'=>'sku','label'=>'Item','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_diamond_color','label'=>'DiamondColor','sortable' =>'true','width' =>50,'type'=>'text'),
array('code'=>'jewelry_diamond_clarity','label'=>'DiamondClarity','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_gemstone_color','label'=>'GemstoneColor','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_gemstone_clarity','label'=>'GemstoneClarity','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_carat_total_weight','label'=>'CaratWeight','sortable' =>'true','width' =>50,'type'=>'float'),
array('code'=>'jewelry_main_stone','label'=>'MainStone','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_metal_purity','label'=>'MetalPurity','sortable' =>'true','width' =>50,'type'=>'text'),
array('code'=>'jewelry_style','label'=>'Style','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_metal','label'=>'Metal','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'special_price','label'=>'SpecialPrice','sortable' =>'true','width' =>100,'type'=>'float'),
array('code'=>'addtocart','type'=>'text'),
array('code'=>'short_description', 'type'=>'text'),
array('code'=>'url_path', 'type'=>'text'),
array('code'=>'image', 'type'=>'text'),
array('code'=>'name', 'type'=>'text')
);
Then I created a function to make fields/columns javascript arrays suitable for my Ext.data.JsonStore requirements
//Fields
if (!function_exists('_setExtField')) {
function _setExtField() {
global $attribute_code;
$field_array = array();
foreach ( $attribute_code as $item =>$value ) {
$field_array[] = "{name: '".$value['code']."', type: '".$value['type']."'}";
}
return implode(',', $field_array);
}
}
//Column
if (!function_exists('_setExtColumn')) {
function _setExtColumn() {
global $attribute_code;
$column_array = array();
foreach ( $attribute_code as $item => $value ) {
if ( isset($value['label']) && $value['label'] != NULL) {
$column_label = $value['label'];
$column_code = $value['code'];
$column_sortable = $value['sortable'];
if ($column_code == 'sku')
$column_array[] = "{id:'$column_code',header: '$column_label', sortable: $column_sortable, renderer: renderUrl, dataIndex: '$column_code'}";
elseif ($column_code == 'special_price')
$column_array[] = "{header: '$column_label', sortable: $column_sortable, renderer: 'usMoney', dataIndex: '$column_code', cellActions:[{iconCls:'x-btn-cart',qtip:'Add this to cart', style: 'background: transparent url(/wp-includes/js/ext/shared/icons/fam/shop_cart.png) no-repeat;'}]}";
else {
$column_array[] = "{header: '$column_label', sortable: $column_sortable, dataIndex: '$column_code'}";
}
}
}
return implode(',', $column_array);
}
}
To make use of a simple html data formatting for each of my data whenever it loads into my grid, I make use of a renderer option
. The renderer option calls a specified javascript function renderUrl and usMoney. usMoney is already built in into Ext-Js library.
Now my Ext.data.JsonStore looks like this:
var store = new Ext.data.JsonStore({
root: 'items', //root tag for all of my items
totalProperty: 'totalcount', // total count tag for my items
idProperty: 'sku',
remoteSort: true, //sort remotely from data
fields: [= _setExtField();?>],
proxy: new Ext.data.ScriptTagProxy({
url: '[your_remote_url'
})
});
Take note root & totalProperty properties. This should be visible in your JSON data. Verifying you JSON data makes it easy at JSON Validator website.
At the proxy property, I make use of Ext.data.ScriptTagProxy class. Using this javascript class requires an extra JSON entry "callback" in your response data. If your remote data script sits in on the same server, using Ext.data.HttpProxy is recommended.
proxy : new Ext.data.HttpProxy({
method: 'POST',
prettyUrls: false,
url: '/remote-data.php?cat=7'
})
You probably want to konw how I did my my "remote-data.php". My remote data sits on a Magento driven web site. As I mention above, "Ext.data.ScriptTagProxy" uses an exra "callback" response. Therefore your php script should have something like this if you want your remote data script usable across domains.
$categoryId = intval(@$_GET['cat']);
$limit = ( isset($_POST['limit']) )? intval(@$_POST['limit']) : intval(@$_GET['limit']) ;
$start = ( isset($_POST['start']) )? intval(@$_POST['start']) : intval(@$_GET['start']) ;
$direction = ( isset($_POST['dir']) )? @$_POST['dir'] : @$_GET['dir'] ;
$sort = ( isset($_POST['sort']) )? @$_POST['sort'] : @$_GET['sort'] ;
//start output
if ( isset($_REQUEST['callback']) ) {
// if you use Ext.data.ScriptTagProxy
$callback = $_REQUEST['callback'];
echo $callback . '(' . json_encode(array('totalcount' => [count], 'items' => [array of items]) ) . ');';
} else {
// if you use Ext.data.HttpProxy
echo json_encode(array('totalcount' => [count], 'items' => [[array of items]]) );
}
Make use of an array_slice function to limit your data as Ext.grid.GridPanel request it. Then create a json data from it by using php arrays and the magical json_encode function
foreach( array_slice(_getProducts($categoryId, $sort, $direction),$start,$limit) as $productId) {
$product = Mage::getModel('catalog/product');
$product->load($productId);
$productTitle = _extSanitize($product->getName());
$productTitleTrim = _trimProductName($productTitle);
$rawData['id'] = $ctr;
$rawData['sku'] = $product->getSku();
$rawData['name'] = $product->getName();
$rawData['url_path'] = $product->getProductUrl();
$rawData['jewelry_style'] = _extSanitize(_getProductAttribute($product , 'jewelry_style'));
$rawData['jewelry_carat_total_weight'] = floatval(_getProductAttribute($product , 'jewelry_carat_total_weight'));
$rawData['jewelry_main_stone'] = _getProductAttribute($product , 'jewelry_main_stone');
$rawData['jewelry_metal_purity'] = _getProductAttribute($product , 'jewelry_metal_purity');
$rawData['jewelry_metal'] = _getProductAttribute($product , 'jewelry_metal');
$rawData['jewelry_diamond_color'] = _getProductAttribute($product , 'jewelry_diamond_color');
$rawData['jewelry_diamond_clarity'] = _getProductAttribute($product , 'jewelry_diamond_clarity');
$rawData['jewelry_gemstone_color'] = _getProductAttribute($product , 'jewelry_gemstone_color');
$rawData['jewelry_gemstone_clarity'] = _getProductAttribute($product , 'jewelry_gemstone_clarity');
$rawData['special_price'] = floatval($product->getSpecialPrice());
$rawData['image'] = $product->getImage();
$rawData['addtocart'] = Mage::getUrl('checkout/cart/add', array('product'=>$productId));
$rawData['short_description'] = $product->getShortDescription();
$items[] = $rawData;
$ctr++;
}
Take note of variable type you are going to declare. It should be the same as you declare it from your Ext.data.JsonStore fields property
$rawData['jewelry_carat_total_weight'] = floatval(_getProductAttribute($product , 'jewelry_carat_total_weight'));
$rawData['special_price'] = floatval($product->getSpecialPrice());
And my demo should be probably be here. Enjoy!
Source:
Remote JSON Data – Response
remote-data.php
Ext.ux.grid.CellActions.js
Credits:
Ext.ux.grid.CellActions Plugin by Saki
ExtJS 3.2.1 API Documentation
Original Ext-JS Paging Example
In my basic grid example, Data was loaded within the javascript call. This post contains an advanced demonstration of using AJAX/JSON to load data remotely for better performance. You will notice that the web page rendered quickly and proceeds before loading the data remotely.
To make use of the fields and columns more efficiently and accurately. I’ve used PHP arrays to construct them as I want to.
global $attribute_code;
$attribute_code = array(
array('code'=>'sku','label'=>'Item','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_diamond_color','label'=>'DiamondColor','sortable' =>'true','width' =>50,'type'=>'text'),
array('code'=>'jewelry_diamond_clarity','label'=>'DiamondClarity','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_gemstone_color','label'=>'GemstoneColor','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_gemstone_clarity','label'=>'GemstoneClarity','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_carat_total_weight','label'=>'CaratWeight','sortable' =>'true','width' =>50,'type'=>'float'),
array('code'=>'jewelry_main_stone','label'=>'MainStone','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_metal_purity','label'=>'MetalPurity','sortable' =>'true','width' =>50,'type'=>'text'),
array('code'=>'jewelry_style','label'=>'Style','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'jewelry_metal','label'=>'Metal','sortable' =>'true','width' =>75,'type'=>'text'),
array('code'=>'special_price','label'=>'SpecialPrice','sortable' =>'true','width' =>100,'type'=>'float'),
array('code'=>'addtocart','type'=>'text'),
array('code'=>'short_description', 'type'=>'text'),
array('code'=>'url_path', 'type'=>'text'),
array('code'=>'image', 'type'=>'text'),
array('code'=>'name', 'type'=>'text')
);
Then I created a function to make fields/columns javascript arrays suitable for my Ext.data.JsonStore requirements
//Fields
if (!function_exists('_setExtField')) {
function _setExtField() {
global $attribute_code;
$field_array = array();
foreach ( $attribute_code as $item =>$value ) {
$field_array[] = "{name: '".$value['code']."', type: '".$value['type']."'}";
}
return implode(',', $field_array);
}
}
//Column
if (!function_exists('_setExtColumn')) {
function _setExtColumn() {
global $attribute_code;
$column_array = array();
foreach ( $attribute_code as $item => $value ) {
if ( isset($value['label']) && $value['label'] != NULL) {
$column_label = $value['label'];
$column_code = $value['code'];
$column_sortable = $value['sortable'];
if ($column_code == 'sku')
$column_array[] = "{id:'$column_code',header: '$column_label', sortable: $column_sortable, renderer: renderUrl, dataIndex: '$column_code'}";
elseif ($column_code == 'special_price')
$column_array[] = "{header: '$column_label', sortable: $column_sortable, renderer: 'usMoney', dataIndex: '$column_code', cellActions:[{iconCls:'x-btn-cart',qtip:'Add this to cart', style: 'background: transparent url(/wp-includes/js/ext/shared/icons/fam/shop_cart.png) no-repeat;'}]}";
else {
$column_array[] = "{header: '$column_label', sortable: $column_sortable, dataIndex: '$column_code'}";
}
}
}
return implode(',', $column_array);
}
}
To make use of a simple html data formatting for each of my data whenever it loads into my grid, I make use of a renderer option
. The renderer option calls a specified javascript function renderUrl and usMoney. usMoney is already built in into Ext-Js library.
Now my Ext.data.JsonStore looks like this:
var store = new Ext.data.JsonStore({
root: 'items', //root tag for all of my items
totalProperty: 'totalcount', // total count tag for my items
idProperty: 'sku',
remoteSort: true, //sort remotely from data
fields: [= _setExtField();?>],
proxy: new Ext.data.ScriptTagProxy({
url: '[your_remote_url'
})
});
Take note root & totalProperty properties. This should be visible in your JSON data. Verifying you JSON data makes it easy at JSON Validator website.
At the proxy property, I make use of Ext.data.ScriptTagProxy class. Using this javascript class requires an extra JSON entry "callback" in your response data. If your remote data script sits in on the same server, using Ext.data.HttpProxy is recommended.
proxy : new Ext.data.HttpProxy({
method: 'POST',
prettyUrls: false,
url: '/remote-data.php?cat=7'
})
You probably want to know how I did my my "remote-data.php". My remote data sits on a Magento driven web site. As I mention above, "Ext.data.ScriptTagProxy" uses an exra "callback" response. Therefore your php script should have something like this if you want your remote data script usable across domains.
$categoryId = intval(@$_GET['cat']);
$limit = ( isset($_POST['limit']) )? intval(@$_POST['limit']) : intval(@$_GET['limit']) ;
$start = ( isset($_POST['start']) )? intval(@$_POST['start']) : intval(@$_GET['start']) ;
$direction = ( isset($_POST['dir']) )? @$_POST['dir'] : @$_GET['dir'] ;
$sort = ( isset($_POST['sort']) )? @$_POST['sort'] : @$_GET['sort'] ;
//start output
if ( isset($_REQUEST['callback']) ) {
// if you use Ext.data.ScriptTagProxy
$callback = $_REQUEST['callback'];
echo $callback . '(' . json_encode(array('totalcount' => [count], 'items' => [array of items]) ) . ');';
} else {
// if you use Ext.data.HttpProxy
echo json_encode(array('totalcount' => [count], 'items' => [[array of items]]) );
}
Make use of an array_slice function to limit your data as Ext.grid.GridPanel request it. Then create a json data from it by using php arrays and the magical json_encode function
foreach( array_slice(_getProducts($categoryId, $sort, $direction),$start,$limit) as $productId) {
$product = Mage::getModel('catalog/product');
$product->load($productId);
$productTitle = _extSanitize($product->getName());
$productTitleTrim = _trimProductName($productTitle);
$rawData['id'] = $ctr;
$rawData['sku'] = $product->getSku();
$rawData['name'] = $product->getName();
$rawData['url_path'] = $product->getProductUrl();
$rawData['jewelry_style'] = _extSanitize(_getProductAttribute($product , 'jewelry_style'));
$rawData['jewelry_carat_total_weight'] = floatval(_getProductAttribute($product , 'jewelry_carat_total_weight'));
$rawData['jewelry_main_stone'] = _getProductAttribute($product , 'jewelry_main_stone');
$rawData['jewelry_metal_purity'] = _getProductAttribute($product , 'jewelry_metal_purity');
$rawData['jewelry_metal'] = _getProductAttribute($product , 'jewelry_metal');
$rawData['jewelry_diamond_color'] = _getProductAttribute($product , 'jewelry_diamond_color');
$rawData['jewelry_diamond_clarity'] = _getProductAttribute($product , 'jewelry_diamond_clarity');
$rawData['jewelry_gemstone_color'] = _getProductAttribute($product , 'jewelry_gemstone_color');
$rawData['jewelry_gemstone_clarity'] = _getProductAttribute($product , 'jewelry_gemstone_clarity');
$rawData['special_price'] = floatval($product->getSpecialPrice());
$rawData['image'] = $product->getImage();
$rawData['addtocart'] = Mage::getUrl('checkout/cart/add', array('product'=>$productId));
$rawData['short_description'] = $product->getShortDescription();
$items[] = $rawData;
$ctr++;
}
Take note of variable type you are going to declare. It should be the same as you declare it from your Ext.data.JsonStore fields property
$rawData['jewelry_carat_total_weight'] = floatval(_getProductAttribute($product , 'jewelry_carat_total_weight'));
$rawData['special_price'] = floatval($product->getSpecialPrice());
And my demo should be probably be here. Enjoy!
Source:
Remote JSON Data – Response
remote-data.php
Ext.ux.grid.CellActions.js
Credits:
Ext.ux.grid.CellActions Plugin by Saki
ExtJS 3.2.1 API Documentation
Original Ext-JS Paging Example
Tagged as Cell Actions, ext-js, ext-js plugin, grid, Grid.Panel, javascript, json, magento + Categorized as Ext-js, Magento