Product ID | Product Name | Quantity Per Unit | Unit Price | Units In Stock | Discontinued | ||
---|---|---|---|---|---|---|---|
41
2<div id="grid_editing" style="margin: auto;">
3</div>
4
1711
2$(function () {
3//called when save changes button is clicked.
4function saveChanges() {
5var grid = $grid.pqGrid('getInstance').grid;
6
7//attempt to save editing cell.
8if (grid.saveEditCell() === false) {
9return false;
10}
11
12if (grid.isDirty() && grid.isValidChange({ focusInvalid: true }).valid) {
13
14var changes = grid.getChanges({ format: "byVal" });
15
16//post changes to server
17$.ajax({
18dataType: "json",
19type: "POST",
20async: true,
21beforeSend: function (jqXHR, settings) {
22grid.showLoading();
23},
24url: "/pro/products/batch", //for ASP.NET, java
25//url:
26data: { list: JSON.stringify(changes) },
27success: function (changes) {
28//debugger;
29grid.commit({ type: 'add', rows: changes.addList });
30grid.commit({ type: 'update', rows: changes.updateList });
31grid.commit({ type: 'delete', rows: changes.deleteList });
32
33grid.history({ method: 'reset' });
34},
35complete: function () {
36grid.hideLoading();
37}
38});
39}
40}
41var obj = {
42hwrap: false,
43resizable: true,
44rowBorders: false,
45virtualX: true,
46filterModel: { header: true, type: 'local' },
47trackModel: { on: true }, //to turn on the track changes.
48toolbar: {
49items: [
50{ type: 'button', icon: 'ui-icon-plus', label: 'New Product', listener: function () {
51//append empty row at the end.
52var rowData = { ProductID: 34, UnitPrice: 0.2 }; //empty row
53var rowIndx = $grid.pqGrid("addRow", { rowData: rowData, checkEditable: true });
54$grid.pqGrid("goToPage", { rowIndx: rowIndx });
55$grid.pqGrid("editFirstCellInRow", { rowIndx: rowIndx });
56}
57},
58{ type: 'separator' },
59{ type: 'button', icon: 'ui-icon-disk', label: 'Save Changes', cls: 'changes', listener: function () {
60saveChanges();
61},
62options: { disabled: true }
63},
64{ type: 'button', icon: 'ui-icon-cancel', label: 'Reject Changes', cls: 'changes', listener: function () {
65$grid.pqGrid("rollback");
66$grid.pqGrid("history", { method: 'resetUndo' });
67},
68options: { disabled: true }
69},
70{ type: 'separator' },
71{ type: 'button', icon: 'ui-icon-arrowreturn-1-s', label: 'Undo', cls: 'changes', listener: function () {
72$grid.pqGrid("history", { method: 'undo' });
73},
74options: { disabled: true }
75},
76{ type: 'button', icon: 'ui-icon-arrowrefresh-1-s', label: 'Redo', listener: function () {
77$grid.pqGrid("history", { method: 'redo' });
78},
79options: { disabled: true }
80}
81]
82},
83scrollModel: { autoFit: true },
84swipeModel: { on: false },
85editModel: {
86saveKey: $.ui.keyCode.ENTER
87},
88editor: { select: true },
89title: "<b>Batch Editing & Filtering & Sorting Combined</b>",
90history: function (evt, ui) {
91var $grid = this.widget();
92if (ui.canUndo != null) {
93$("button.changes", $grid).button("option", { disabled: !ui.canUndo });
94}
95if (ui.canRedo != null) {
96$("button:contains('Redo')", $grid).button("option", "disabled", !ui.canRedo);
97}
98$("button:contains('Undo')", $grid).button("option", { label: 'Undo (' + ui.num_undo + ')' });
99$("button:contains('Redo')", $grid).button("option", { label: 'Redo (' + ui.num_redo + ')' });
100},
101colModel: [
102{ title: "Product ID", dataType: "integer", dataIndx: "ProductID", editable: false, width: 80 },
103{ title: "Product Name", width: 165, dataType: "string", dataIndx: "ProductName",
104filter: { type: 'textbox', condition: 'begin', listeners: ['keyup'] },
105validations: [
106{ type: 'minLen', value: 1, msg: "Required" },
107{ type: 'maxLen', value: 40, msg: "length should be <= 40" }
108]
109},
110{ title: "Quantity Per Unit", width: 140, dataType: "string", dataIndx: "QuantityPerUnit",
111validations: [
112{ type: 'minLen', value: 1, msg: "Required." },
113{ type: 'maxLen', value: 20, msg: "length should be <= 20" }
114]
115},
116{ title: "Unit Price", width: 100, dataType: "float", dataIndx: "UnitPrice", format: '$##,###.00',
117validations: [{ type: 'gt', value: 0.5, msg: "should be > 0.5"}]
118},
119//{ hidden: true },
120{ title: "Units In Stock", width: 100, dataType: "integer", dataIndx: "UnitsInStock",
121validations: [
122{ type: 'gte', value: 1, msg: "should be >= 1" },
123{ type: 'lte', value: 1000, msg: "should be <= 1000" }
124]
125},
126{ title: "Discontinued", width: 100, dataType: "bool", align: "center", dataIndx: "Discontinued",
127editor: { type: "checkbox", subtype: 'triple',
128style: "margin:3px 5px;"
129
130},
131validations: [{ type: 'nonEmpty', msg: "Required"}]
132},
133{ title: "", editable: false, minWidth: 83, sortable: false,
134render: function (ui) {
135return "<button type='button' class='delete_btn'>Delete</button>";
136},
137postRender: function (ui) {
138var rowIndx = ui.rowIndx,
139grid = this,
140$cell = grid.getCell(ui);
141
142$cell.find("button").button({ icons: { primary: 'ui-icon-scissors'} })
143.bind("click", function () {
144
145grid.addClass({ rowIndx: ui.rowIndx, cls: 'pq-row-delete' });
146
147var ans = window.confirm("Are you sure to delete row No " + (rowIndx + 1) + "?");
148grid.removeClass({ rowIndx: rowIndx, cls: 'pq-row-delete' });
149if (ans) {
150grid.deleteRow({ rowIndx: rowIndx });
151}
152});
153}
154}
155],
156postRenderInterval: -1, //call postRender synchronously.
157pageModel: { type: "local", rPP: 20 },
158dataModel: {
159dataType: "JSON",
160location: "remote",
161recIndx: "ProductID",
162url: "/pro/products/get", //for ASP.NET
163//url: "/pro/products.php", //for PHP
164getData: function (response) {
165return { data: response.data };
166}
167}
168};
169var $grid = $("#grid_editing").pqGrid(obj);
170});
171
x1
2div.pq-toolbar button
3{
4margin:0px 5px;
5}
6button.delete_btn
7{
8margin:-3px 0px;
9}
10tr.pq-row-delete
11{
12text-decoration:line-through;
13}
14tr.pq-row-delete td
15{
16background-color:pink;
17}
18
1031
2//Model class
3public class Product
4{
5public int ProductID { get; set; }
6public String ProductName { get; set; }
7public String QuantityPerUnit { get; set; }
8public decimal UnitPrice { get; set; }
9public short UnitsInStock { get; set; }
10public short UnitsOnOrder { get; set; }
11public short ReorderLevel { get; set; }
12public bool Discontinued { get; set; }
13}
14public partial class productsController : Controller
15{
16private void addList(List<Product> addList)
17{
18List<Product> products = ((List<Product>)Session["Products"]);
19int max;
20if (products.Count == 0)
21{
22max = 0;
23}
24else
25{
26max = products.OrderByDescending(x => x.ProductID).First().ProductID;
27}
28
29for (int i = 0; i < addList.Count; i++)
30{
31Product product = addList[i];
32product.ProductID = max + 1 + i;
33products.Add(product);
34}
35}
36private void updateList(List<Product> updateList)
37{
38List<Product> products = ((List<Product>)Session["Products"]);
39
40for (int i = 0; i < updateList.Count; i++)
41{
42Product product2 = updateList[i];
43
44Product product = products.Find(Product => Product.ProductID == product2.ProductID);
45if (product == null)
46{
47products.Add(product2);
48}
49else
50{
51product.ProductID = product2.ProductID;
52product.ProductName = product2.ProductName;
53product.QuantityPerUnit = product2.QuantityPerUnit;
54product.UnitPrice = product2.UnitPrice;
55product.UnitsInStock = product2.UnitsInStock;
56product.UnitsOnOrder = product2.UnitsOnOrder;
57product.Discontinued = product2.Discontinued;
58}
59}
60}
61private void deleteList(List<Product> deleteList)
62{
63List<Product> products = ((List<Product>)Session["Products"]);
64
65for (int i = 0; i < deleteList.Count; i++)
66{
67Product product2 = deleteList[i];
68Product product = products.Find(Product => Product.ProductID == product2.ProductID);
69products.Remove(product);
70}
71}
72[HttpPost]
73public String batch(String list)
74{
75fillInSession();
76
77JavaScriptSerializer js = new JavaScriptSerializer();
78Dictionary<String, List<Product>> dlist = js.Deserialize<Dictionary<String, List<Product>>>(list);
79
80this.updateList(dlist["updateList"]);
81this.addList(dlist["addList"]);
82this.deleteList(dlist["deleteList"]);
83return js.Serialize(dlist);
84}
85public ActionResult get()
86{
87fillInSession();
88var products2 = (from product in (List<Product>)Session["Products"]
89orderby product.ProductName
90select product);
91
92StringBuilder sb = new StringBuilder(@"{""data"":");
93
94JavaScriptSerializer js = new JavaScriptSerializer();
95
96string json = js.Serialize(products2);
97sb.Append(json);
98sb.Append("}");
99
100return this.Content(sb.ToString(), "text/text");
101}
102}
103
1631
2//products.php
3<?php
4require_once 'conf.php';
5
6function addList($addList)
7{
8$sproducts = json_decode($_SESSION["Products"], true);
9//sort by product ID to get max ProductID
10usort($sproducts, function($a, $b)
11{
12return ($a["ProductID"] > $b["ProductID"]);
13});
14$max = $sproducts[sizeof($sproducts)-1]["ProductID"];
15
16//get $product by reference.
17foreach ($addList as $i=> &$product)
18{
19$product["ProductID"] = $max + 1 + $i;
20
21$sproduct = array();
22copyproduct($sproduct, $product);
23$sproducts[]=$sproduct;
24
25//$products[]=$product;//add new product
26}
27$_SESSION["Products"]= json_encode($sproducts);
28return $addList;
29}
30function copyproduct(&$sproduct, $uproduct){
31$sproduct["ProductID"] = $uproduct["ProductID"];
32$sproduct["ProductName"] = $uproduct["ProductName"];
33$sproduct["QuantityPerUnit"] = $uproduct["QuantityPerUnit"];
34$sproduct["UnitPrice"] = $uproduct["UnitPrice"];
35$sproduct["UnitsInStock"] = $uproduct["UnitsInStock"];
36//$product["UnitsOnOrder"] = $product2["UnitsOnOrder"];
37$sproduct["Discontinued"] = $uproduct["Discontinued"];
38}
39function updateList($updateList)
40{
41$sproducts = json_decode($_SESSION["Products"], true);
42
43foreach ($updateList as $uproduct)
44{
45$ProductID = $uproduct["ProductID"];
46$found=false;
47foreach($sproducts as $i => &$sproduct){
48if($sproduct["ProductID"] == $ProductID){
49//$products[$i] = $product2;
50copyproduct($sproduct, $uproduct);
51$found=true;
52break;
53}
54}
55if(!$found){
56//add new product if not found.
57$sproduct = array();
58copyproduct($sproduct, $uproduct);
59$sproducts[]=$sproduct;
60}
61}
62$_SESSION["Products"]= json_encode($sproducts);
63return $updateList;
64}
65function deleteList($deleteList)
66{
67$products = json_decode($_SESSION["Products"], true);
68
69foreach ($deleteList as $product)
70{
71$ProductID = $product["ProductID"];
72foreach($products as $i => $product2){
73if($product2["ProductID"] == $ProductID){
74unset($products[$i]);
75break;
76}
77}
78}
79$_SESSION["Products"]= json_encode($products);
80return $deleteList;
81}
82if( isset($_GET["pq_batch"]))
83{
84session_start();
85$dlist = $_POST['list'];
86
87if(isset($dlist["updateList"])){
88$dlist["updateList"] = updateList($dlist["updateList"]);
89}
90if(isset($dlist["addList"])){
91$dlist["addList"] = addList($dlist["addList"]);
92}
93if(isset($dlist["deleteList"])){
94$dlist["deleteList"] = deleteList($dlist["deleteList"]);
95}
96
97echo json_encode($dlist);
98}
99else{
100session_start();
101$_SESSION["Products"]=null;
102if (isset($_SESSION["Products"])==false)
103{
104//add in session["Products"];
105$sql = "Select ProductID, ProductName, QuantityPerUnit, UnitPrice, UnitsInStock, Discontinued from products";
106$dsn = 'mysql:host='.DB_HOSTNAME.';dbname='.DB_NAME;
107$options = array(
108PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
109);
110$dbh = new PDO($dsn, DB_USERNAME, DB_PASSWORD, $options);
111$stmt = $dbh->prepare($sql);
112$stmt->execute();
113$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
114foreach ($rows as $i=> &$row)
115{
116if($row['Discontinued']=='0'){
117$row['Discontinued']=false;
118}
119else{
120$row['Discontinued']=true;
121}
122}
123
124$_SESSION["Products"]= json_encode($rows);
125}
126$products = json_decode($_SESSION["Products"], true);
127if(isset($_GET["pq_curpage"]) && isset($_GET["pq_rpp"]) )
128{
129$pq_curPage = $_GET["pq_curpage"];
130$pq_rPP=$_GET["pq_rpp"];
131
132$total_Records = sizeof($products);
133
134$skip = ($pq_rPP * ($pq_curPage - 1));
135
136if ($skip >= $total_Records)
137{
138$pq_curPage = ceil($total_Records / $pq_rPP);
139$skip = ($pq_rPP * ($pq_curPage - 1));
140}
141//sort by Product name
142usort($products, function($a, $b)
143{
144return strcmp($a["ProductName"], $b["ProductName"]);
145});
146$products2=array();
147for( $i=$skip; $i<($skip+$pq_rPP); $i++ ){
148if($i>=$total_Records){
149break;
150}
151$products2[]=$products[$i];
152}
153$sb = "{\"totalRecords\":" . $total_Records . ",\"curPage\":" . $pq_curPage . ",\"data\":".json_encode($products2)."}";
154echo $sb;
155}
156else{
157$sb = "{\"data\":".json_encode($products)."}";
158echo $sb;
159}
160}
161
162?>
163
1561
2package controller;
3
4import domain.Product;
5import flexjson.JSONSerializer;
6import flexjson.JSONDeserializer;
7import java.util.ArrayList;
8import java.util.List;
9import java.util.Map;
10import javax.servlet.http.HttpServletRequest;
11import javax.servlet.http.HttpSession;
12import org.apache.commons.logging.Log;
13import org.apache.commons.logging.LogFactory;
14import org.springframework.jdbc.core.BeanPropertyRowMapper;
15import org.springframework.jdbc.core.support.JdbcDaoSupport;
16import org.springframework.stereotype.Controller;
17import org.springframework.ui.ModelMap;
18import org.springframework.web.bind.annotation.*;
19
20/**
21* @author paramvir
22* batch editing & instant editing demo
23*/
24@Controller
25public class ProductsListController extends JdbcDaoSupport {
26
27protected final Log logger = LogFactory.getLog(getClass());
28
29private HttpSession fillInSession(HttpServletRequest request){
30HttpSession ses = request.getSession(true);
31//ses.setAttribute("Products", null);
32if(ses.getAttribute("Products")==null){
33logger.info("ses is null");
34List<Product> products = getJdbcTemplate().query(
35"Select productid, ProductName, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued from products",
36new BeanPropertyRowMapper(Product.class));
37
38ses.setAttribute("Products", products);
39}
40return ses;
41}
42private String serialize(List<Product> products){
43JSONSerializer serializer = new JSONSerializer().exclude("*.class");
44String str = serializer.serialize(products);
45return str;
46}
47private String serializeMap(Map<String, List<Product>> map){
48JSONSerializer serializer = new JSONSerializer().exclude("*.class");
49String str = serializer.deepSerialize(map);
50return str;
51}
52private Map deserializeMap(String str){
53JSONDeserializer<Map<String, List<Product>>> deserializer = new JSONDeserializer<Map<String, List<Product>>>();
54Map<String, List<Product>> map = deserializer.use( "values.values", Product.class ).deserialize(str);
55
56return map;
57}
58@RequestMapping(value="/products/clear", method=RequestMethod.GET)
59public @ResponseBody String clear(HttpServletRequest request ){
60HttpSession ses = fillInSession(request);
61//ses.setAttribute("Products", "");
62List<Product> products = (List<Product>)ses.getAttribute("Products");
63products.clear();
64return "";
65}
66private void updateList(ArrayList updateList, HttpSession ses ){
67
68List<Product> products = (List<Product>)ses.getAttribute("Products");
69
70for (int i = 0; i < updateList.size(); i++)
71{
72Product updateProduct = (Product)updateList.get(i);
73int ProductID = updateProduct.getProductID();
74for(int j = 0 ; j < products.size() ; j++ ){
75Product sessionProduct = products.get(j);
76if(ProductID == sessionProduct.getProductID()){
77products.set(j, updateProduct);
78break;
79}
80}
81}
82ses.setAttribute("Products", products);
83}
84private int getMaxProductID(List<Product> products){
85int max=0;
86for(int j = 0 ; j < products.size() ; j++ ){
87Product product = products.get(j);
88int ProductID = product.getProductID();
89if(ProductID > max){
90max = ProductID;
91}
92}
93return max;
94}
95public void addList(ArrayList addList, HttpSession ses ){
96
97List<Product> products = (List<Product>)ses.getAttribute("Products");
98int max = getMaxProductID(products);
99
100for (int i = 0; i < addList.size(); i++)
101{
102Product addProduct = (Product)addList.get(i);
103addProduct.setProductID(max+1+i);
104products.add(addProduct);
105}
106}
107private void deleteList(ArrayList deleteList, HttpSession ses ){
108
109List<Product> products = (List<Product>)ses.getAttribute("Products");
110
111for (int i = 0; i < deleteList.size(); i++)
112{
113Product deleteProduct = (Product)deleteList.get(i);
114int ProductID = deleteProduct.getProductID();
115
116for(int j = 0 ; j < products.size() ; j++ ){
117Product sessionProduct = products.get(j);
118if(ProductID == sessionProduct.getProductID()){
119products.remove(sessionProduct);
120break;
121}
122}
123}
124ses.setAttribute("Products", products);
125}
126@RequestMapping(value="/products/batch", method=RequestMethod.POST)
127public @ResponseBody String batch(@RequestParam String list, HttpServletRequest request ){
128HttpSession ses = fillInSession(request);
129
130Map dlist = deserializeMap(list);
131
132ArrayList updateList = (ArrayList)dlist.get("updateList");
133ArrayList addList = (ArrayList)dlist.get("addList");
134ArrayList deleteList = (ArrayList)dlist.get("deleteList");
135
136this.updateList(updateList, ses);
137this.addList(addList, ses);
138this.deleteList(deleteList, ses);
139
140return serializeMap(dlist);
141}
142//get all products
143@RequestMapping(value="/products/get",method=RequestMethod.GET)
144public @ResponseBody String products(ModelMap model, HttpServletRequest request ){
145
146HttpSession ses = fillInSession(request);
147
148List<Product> products = (List<Product>)ses.getAttribute("Products");
149
150String serializedProducts = serialize(products);
151
152String responseStr = "{\"data\":" + serializedProducts + "}";
153return responseStr;
154}
155}
156