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
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;
}
}
|