Articles: 843 | Categories: 148   
   
   
Home Articles Contact Us
 
 
 
 
Using Ext grid form dialog to achieve paging list, create, edit, delete function (0 Comments)
Admin: Posted Date: April 4, 2010

In web applications, most of the pages can be cataloged as: List, Create, Read, Update, Delete.The Ext documentation center provides a good example for an inline editing grid. However, in many cases, an inline editing grid is not enough and a pop-up dialog is needed to achieve different kinds of fields in our form. Below is one of my simple examples to show you how to create/update a dialog form based on a user action in the grid.

Using Ext grid

In web applications, most of the pages can be cataloged as: List, Create, Read, Update, Delete. The Ext documentation center provides a good example for an inline editing grid. However, in many cases, an inline editing grid is not enough and a pop-up dialog is needed to achieve different kinds of fields in our form. Below is one of my simple examples to show you how to create/update a dialog form based on a user action in the grid.

List function

Error creating thumbnail:
libgomp: Thread creation failed: Cannot allocate memory
List Account
Update Account
Delete Account
Create Account

This is the list accounts page, it includes paging, search/filter function, add and delete function.

Add filter/search drop-down menu in the Grid head panel.

/************************************************************
* create header panel 
* add filter field - search function
************************************************************/
var gridHead = grid.getView().getHeaderPanel(true);
var tb = new Ext.Toolbar(gridHead);
 
filterButton = new Ext.Toolbar.MenuButton({
icon: 'public/image/list-items.gif',
cls: 'x-btn-text-icon',
text: 'Choose Filter',
tooltip: 'Select one of filter',
menu: {items: [
new Ext.menu.CheckItem({ text: 'First Name', value: 'firstname', checked: true, group: 'filter',checkHandler:onItemCheck }),
new Ext.menu.CheckItem({ text: 'Last Name', value: 'lastname', checked: false, group: 'filter', checkHandler: onItemCheck }),
new Ext.menu.CheckItem({ text: 'Username', value: 'username', checked: false, group: 'filter', checkHandler: onItemCheck })	
]},
minWidth: 105
});
tb.add(filterButton);
 
// Create the filter field
var filter = Ext.get(tb.addDom({ // add a DomHelper config to the toolbar and return a reference to it
tag: 'input', 
type: 'text', 
size: '30', 
value: '', 
style: 'background: #F0F0F9;'
}).el);			
 
// press enter keyboard
filter.on('keypress', function(e) { // setup an onkeypress event handler
if(e.getKey() == e.ENTER && this.getValue().length > 0) {// listen for the ENTER key
ds.load({params:{start:0, limit:myPageSize}});
}
});

Add paging, add and delete button in the Grid footer panel.

/************************************************************
* create footer panel 
*    actions and paging
************************************************************/ 
var gridFoot = grid.getView().getFooterPanel(true);
 
// add a paging toolbar to the grid's footer
var paging = new Ext.PagingToolbar(gridFoot, ds, {
pageSize: myPageSize,
displayInfo: true,
displayMsg: 'total {2} results found. Current shows {0} - {1}',
emptyMsg: "not result to display"
});
// add the detailed add button
paging.add('-', {
pressed: true,
enableToggle:true,
text: 'Add',
cls: '',
toggleHandler: doAdd
});    
// add the detailed delete button
paging.add('-', {
pressed: true,
enableToggle:true,
text: 'Delete',
cls: '',
toggleHandler: doDel
});

 

On paging function, you need send filterTxt and value to server before loading data.

/************************************************************
* load parameter to backend 
*    have beforelaod function
************************************************************/
ds.on('beforeload', function() {
ds.baseParams = { // modify the baseParams setting for this request
filterValue: filter.getValue(),// retrieve the value of the filter input and assign it to a property named filter 
filterTxt: filterButton.getText()
};
});
// trigger the data store load
ds.load({params:{start:0, limit:myPageSize}});

List result get JSON data from server-side:

({"totalCount":52,"results":[{"lastname":"Zhuang","password":"12","firstname":"Fenqiang"
,"enterDate":"Jun 18, 2007","username":"ffzhuang","id":40},{"lastname":"gh","password":"gh","firstname":"gh-last","enterDate":"Jun 18, 2007","username":"gh","id":11}]})

Delete function

Delete function will get the selected id(s) and create JSON data and send JSON data to Java server-side for handle.

/************************************************************
* Action - delete
*   start to handle delete function
*   need confirm to delete
************************************************************/	
function doDel(){
var m = grid.getSelections();
if(m.length > 0)
{
Ext.MessageBox.confirm('Message', 'Do you really want to delete it?' , doDel2);	
}
else
{
Ext.MessageBox.alert('Message', 'Please select at least one item to delete');
}
}     
 
function doDel2(btn)
{
if(btn == 'yes')
{	
var m = grid.getSelections();
var jsonData = "[";
for(var i = 0, len = m.length; i < len; i++){        		
var ss = "{"id":"" + m[i].get("id") + ""}";
//alert(ss);
if(i==0)
jsonData = jsonData + ss ;
else
jsonData = jsonData + "," + ss;	
ds.remove(m[i]);								
}	
jsonData = jsonData + "]";
ds.load({params:{start:0, limit:myPageSize, delData:jsonData}});		
}
}

And delete parameter to server side with JSON data like this: delData=[{"id":"5"},{"id":"6"}]

 

Add function

Add function will pop-up a form dialog to let client enter information for save.

/************************************************************
*  To create add new account dialog now....
************************************************************/   
function doAdd(){
var aAddInstanceDlg;
 
if (!aAddInstanceDlg) {
aAddInstanceDlg = createNewDialog("a-addInstance-dlg");       
aAddInstanceDlg.addButton('Reset', resetForm, aAddInstanceDlg);
aAddInstanceDlg.addButton('Save', function() {       
// validation now
if (password_tf.getValue()!=cPassword_tf.getValue()) {
password_tf.markInvalid("passwords not match");
password_tf.focus();
return; 
}
 
// submit now... all the form information are submit to the server
// handle response after that...
if (form_instance_create.isValid()) {
form_instance_create.submit({
waitMsg:'Creating new account now...',
reset: false,
failure: function(form_instance_create, action) {
Ext.MessageBox.alert('Error Message', action.result.errorInfo);
},
success: function(form_instance_create, action) {
Ext.MessageBox.alert('Confirm', action.result.info);
aAddInstanceDlg.hide();
ds.load({params:{start:0, limit:myPageSize}});
}
});					
}else{
Ext.MessageBox.alert('Errors', 'Please fix the errors noted.');
}	    	
});
 
var layout = aAddInstanceDlg.getLayout();
layout.beginUpdate();
layout.add('center', new Ext.ContentPanel('a-addInstance-inner', {title: 'create account'}));
layout.endUpdate(); 
 
aAddInstanceDlg.show();
};        
}

Java server side code to handle add function

protected ActionForward createAccount(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception
{
Account account = AccountUtil.setAccount(request);
 
// check condition now...validation
JSONObject errors = new JSONObject();
AccountService accountService = new AccountService();
if (accountService.isUsernameExist(account.getUsername()))
{
errors.put("id", "username");
errors.put("msg",
"this username also in use, please select another one");
}
 
// if any validation errors
if (errors.length() > 0)
{
// set response now with json format
System.out.println("have error now...");
JsonMVCUtil.jsonErrorsResponse(errors, request, response);
} else
{
// save this object
try
{
account.setCreationDate(new Date());
accountService.createOrUpdate(account);
JsonMVCUtil.jsonOkResponse(
"You have successfully created this accout", request,
response);
} catch (Exception e)
{
JsonMVCUtil
.jsonFailResponse("Internal Error, please try again",
request, response);
}
}
 
return null;
}

Update function

User will select one of rows in the list and double click this row. Update function will fetch the data from server-side by user selected id and show the result in dialog form for client to update. When user update the form information and submit the result to server, there have 2 kinds of validation, one is client side (isValid and markInvalid), another is from server side during update failed (JSON data).

In general, it need transfer a hidden "id" to server side for update. We can put this id (and any hidden fields) as one of params during submit form.

/************************************************************
* Action - update
*   handle double click 
*   user select one of the item and want to update it
************************************************************/
grid.on('rowdblclick', function(grid, rowIndex, e) {
var selectedId = ds.getAt(rowIndex).id;
 
// Get information from DB and set form now...
// Only need to use a ScriptTagProxy if the URL is at another domain
var account_data = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url:'/yuiExt/listAccount.do?action=loadData&id=' + selectedId}),
reader: new Ext.data.JsonReader({},['id','firstname','password','username','lastname']),
remoteSort: false
});
 
account_data.on('load', function() {
 
// set value now
var newRec = account_data.getAt(0);
var updateId = newRec.data['id'];
username_show.setValue(newRec.get('username'));
firstname_show.setValue(newRec.get('firstname'));
lastname_show.setValue(newRec.get('lastname'));
password_show.setValue(newRec.get('password'));
cPassword_show.setValue(newRec.get('password'));
 
var updateInstanceDlg;        
if (!updateInstanceDlg) {
updateInstanceDlg = createNewDialog("a-updateInstance-dlg"); 
updateInstanceDlg.addButton('Save', function() {       
// validation now
if (password_show.getValue()!=cPassword_show.getValue()) {
password_show.markInvalid("passwords not match");
password_show.focus();
return; 
}
 
// submit now... all the form information are submit to the server
// handle response after that...
if (form_instance_update.isValid()) {
form_instance_update.submit({
params:{id : updateId},
waitMsg:'Updating this account now...',
reset: false,
failure: function(form_instance_update, action) {
Ext.MessageBox.alert('Error Message', action.result.errorInfo);
},
success: function(form_instance_update, action) {
Ext.MessageBox.alert('Confirm', action.result.info);
updateInstanceDlg.hide();
ds.load({params:{start:0, limit:myPageSize}});
}
});					
}else{
Ext.MessageBox.alert('Errors', 'Please fix the errors noted.');
}	    	
});
 
var layout = updateInstanceDlg.getLayout();
layout.beginUpdate();
layout.add('center', new Ext.ContentPanel('a-updateInstance-inner', {title: 'Update Account'}));
layout.endUpdate(); 
 
updateInstanceDlg.show();
}  
}); 
 
account_data.load();	    
});

This is the JSON data transfer from server-side.

([{"lastname":"11","password":"12","firstname":"11-12345","enterDate":"Jun 16, 2007","username":"ffzhuang","id":40}]);

Handle JSON data in Java server side

To create a JSON object in server side with Java. We can use the lib in "json.org". It provides a quick API to parse POJO and list etc. See the following example code:

public JSONObject toJSONObject() throws Exception {
JSONObject json = new JSONObject();
json.put("totalCount", totalCount);
 
JSONArray jsonItems = new JSONArray();
for (Iterator iter = results.iterator(); iter.hasNext();) {
jsonItems.put(iter.next().toJSONObject());
}
json.put("results", jsonItems);
 
return json;
}

To parse JSON data from JS in serve side, please see the following example:

JSONArray jsonArray = JsonUtil.getJsonArray(jsonString);
// JsonUtil.getJsonArray(jsonString) just do this ->
// jsonArray = new JSONArray(jsonString);
 
// loop through - get from json and update
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String id = jsonObject.getString("id");
}

Here is the general JSON response Java function. You need set the ContentType as application/x-json type.

public static void jsonResponse(JSONObject jsonData,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
// check whether it is script Tag...
// which is called by JSON
boolean scriptTag = false;
String cb = request.getParameter("callback");
if (cb != null) {
scriptTag = true;
response.setContentType("text/javascript");
} else {
response.setContentType("application/x-json");
}
 
PrintWriter out = response.getWriter();
if (scriptTag) {
out.write(cb + "(");
}			
response.getWriter().print(jsonData);
if (scriptTag) {
out.write(");");
}
}

Here is the class to load data and create a JSON response to fill the form

private ActionForward loadData(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
// get id first
String accountId = (String) request.getParameter("id").trim();
AccountService accountService = new AccountService();
Account account = accountService.loadAccountById(new Long(accountId));
 
// push data back to Ajax page
JsonMVCUtil.jsonResponse(account.toJSONObject(), request, response);
 
return null;
}

Here is my POJO account class

public class Account extends BaseObject
{
private static final long serialVersionUID = -2384479668303690161L;
private String username = null;
private String password = null;
private String firstName = "";
private String lastName = "";
private String phone = "";
private String emailAddress = "";
private Date creationDate = new Date();
private String activeYN = "active";
 
// get set function
 
/**
* This will create a JSON object and output to client. Get the data from
* database and display result to GUI
* 
* @return
* @throws Exception
*/
public JSONObject toJSONObject() throws Exception
{
String enterDateString = DateUtil
.format(creationDate, "MMM dd, yyyy");
JSONObject json = new JSONObject();
json.put("username", username);
json.put("password", password);
json.put("firstname", firstName);
json.put("id", id);
json.put("lastname", lastName);
json.put("enterDate", enterDateString);
 
return json;
}
}

 

 
 
Add a Comment:
 
(You must be signed in to comment on an article. Not a member? Click here to register)
   
Title:

Comments: