Blog Archive

ExtJs 4 Grid Editing Tutorial based on CellEditing plugin using Java Servlet, JSON and MySQL database

The Ext.grid.plugin.CellEditing plugin injects editing at a cell level for a Grid. Only a single cell will be editable at a time. The field that will be used for the editor is defined at the editor. If an editor is not specified for a particular column then that cell will not be editable and it will be skipped when activated via the mouse or the keyboard.


This tutorial will cover the following topics ...
  • Connection to a Customer Table in MySQL database
  • Get list of customers as JSON array from Java Servlet
  • Edit a customer information using the Grid Cells
  • Add a new customer using the Grid after all validation passes
  • CheckColumn to make the customer record active or inactive
  • Automatically Sync data as soon as the changes are made using AJAX


ExtJs 4 Grid Editing Tutorial using the CellEditing plugin, Java servlet and MySQL
ExtJs 4 Grid Editing Tutorial using the CellEditing plugin, Java servlet and MySQL
ExtJs 4 Grid Editing Tutorial using the CellEditing plugin, Java servlet and MySQL

Application starting point index.html

<html>
<head>
    <title>ExtJs 4 Grid Editing Example </title>

    <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">
    <link rel="stylesheet" type="text/css" href="extjs/ux/css/CheckHeader.css">
   
    <script type="text/javascript" src="extjs/ext-all-debug.js"></script>
    <script type="text/javascript" src="app.js"></script>

</head>
<body></body>
</html>

Application JavaScript file app.js

Ext.Loader.setPath('Ext.ux', 'extjs/ux');

Ext.Loader.setConfig({ 
    enabled: true 
    });

Ext.require([
             'Ext.data.*',
             'Ext.grid.*',
             'Ext.ux.CheckColumn'
         ]);

Ext.application({
    name: 'GRIDEDITING',

    appFolder: 'app',
   
    controllers: [
                  'Customers'
              ],

    launch: function() {
        Ext.create('Ext.container.Viewport', {
            items: [
                {
                    xtype: 'customerList',
                }
            ]
        });
    }
});

JavaScript source file for the Model Customer.js

Ext.define('GRIDEDITING.model.Customer', {
    extend: 'Ext.data.Model',
    fields: [
             'customerId',
             'firstName',
             'lastName',
             'email',
             {name: 'active', type: 'bool'}
            ],
    validations: 
            [
                  {type: 'presence',  field: 'firstName'},
                  {type: 'presence',  field: 'lastName'},
                  {type: 'presence',  field: 'email'}
             ]
});

JavaScript source file for the Store Customers.js

Ext.define('GRIDEDITING.store.Customers', {
    extend: 'Ext.data.Store',
    model: 'GRIDEDITING.model.Customer',
    autoLoad: true,
    pageSize: 20,
    proxy: {
        type: 'ajax',
        url: 'CustomerServlet',
        extraParams: {
            store_id: 1
        },
        reader: {
            type: 'json',
            totalProperty: 'totalCount',
            root: 'customers',
            successProperty: 'success'
        },
     },
   
     listeners: {
         load : function(store) {
             //if need something to do after the store loads
         } 
     }

});

JavaScript source file for Editable Grid view CustomerList.js

Ext.define('GRIDEDITING.view.CustomerList' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.customerList',
    title : 'List of Customers',
    store : 'Customers',
    loadMask: true,
    autoheight: true,
    dockedItems: [{
        xtype: 'pagingtoolbar',
        store: 'Customers',  
        dock: 'bottom',
        displayInfo: true,
        items: [
                { 
                    xtype: 'tbseparator' 
                },
                {
                    xtype : 'button',
                    text: 'Add Customer',
                    action: 'add'
                }
        ]
    }],
    plugins: [
              Ext.create('Ext.grid.plugin.CellEditing', {
                  clicksToEdit: 1
             })        
    ],
    selModel: {
        selType: 'cellmodel'
    },
    initComponent: function() {
       
        this.columns = [{
            header: 'Customer Id', 
            dataIndex: 'customerId',
            flex: 1,
        }, {
            header: 'Active',
            dataIndex: 'active',
            flex: 1,
            xtype: 'checkcolumn',
        }, {
            header: 'First Name',
            dataIndex: 'firstName',
            flex: 1,
            editor: {
                allowBlank: false
            }
        }, {
            header: 'Last Name',
            dataIndex: 'lastName',
            flex: 1,
            editor: {
                allowBlank: false
            }
        }, {
            header: 'Email Address', 
            dataIndex: 'email', 
            flex: 1,
            editor: {
                allowBlank: false,
                vtype: 'email'
            }
        }];

        this.callParent(arguments);
    }
  
  
});

JavaScript source file for the application controller Customers.js

Ext.define('GRIDEDITING.controller.Customers', {
            extend : 'Ext.app.Controller',

            //define the stores
            stores : ['Customers'],
            //define the models
            models : ['Customer'],
            //define the views
            views : ['CustomerList'],
           
            init : function() {
                this.control({
                   
                    'viewport' : {
                        render : this.onPanelRendered
                    },
                    'customerList': {
                        edit: this.editCustomer
                    },
                    'checkcolumn': {
                        checkchange: this.checkboxChanged
                    },
                    'customerList button[action=add]' : {
                        click : this.addCustomer   
                    }   
                });
            },

            onPanelRendered : function() {
                //just a console log to show when the panel is rendered
                console.log('The panel was rendered');
            },
           
            editCustomer : function(editor, obj) {
                //check if record is dirty 
                if(obj.record.dirty){
                    //check if the record is valid   
                    console.log(obj.record.validate());
                    if(obj.record.validate().isValid()){
                        //Make your Ajax request to sync data
                        mode = (obj.record.get('customerId') === "") ? 'insert': 'update';
                        this.syncData(obj.rowIdx, mode);
                    }
                }
            },
           
            checkboxChanged : function(column,rowIndex,checked) {
                console.log('Checkbox changed');
                //grid column information
                console.log(column);
                //grid row number
                console.log(rowIndex);
                //the checkbox value
                console.log(checked);
                console.log(this.getCustomersStore().getAt(rowIndex));
                //Make your Ajax request to sync data
                this.syncData(rowIndex,'update');
            },
           
            //Sync data with the server 
            syncData : function(rowIndex, mode) {
                Ext.Ajax.request({
                       url: 'CustomerServlet',
                    params: {
                            store_id: 1,
                            action: mode,
                            rowIndex: rowIndex,
                            recordInfo: Ext.encode(this.getCustomersStore().getAt(rowIndex).data)
                    },
                    scope:this,
                    //method to call when the request is successful
                    success: this.onSaveSuccess,
                    //method to call when the request is a failure
                    failure: this.onSaveFailure
                });
            },
           
            onSaveFailure: function(err){
                //Alert the user about communication error
                Ext.MessageBox.alert('Status', 'Error occured during update');
            },
   
            onSaveSuccess: function(response,opts){
                //Remove dirty
                var ajaxResponse = Ext.decode(response.responseText);
                if(ajaxResponse.success){
                    //if we are doing an insert then get the new customerId 
                    //and update the store record
                    if(opts.params.action === 'insert'){
                        customerId = ajaxResponse.customerId;
                        this.getCustomersStore().getAt(opts.params.rowIndex).set('customerId',customerId);
                    }
                    this.getCustomersStore().getAt(opts.params.rowIndex).commit();
                }
                else {
                    Ext.MessageBox.alert('Status', 'Error occured during update');
                }
            },
           
            addCustomer : function(button) {
                var customer = new GRIDEDITING.model.Customer({
                                        'customerId': '',
                                        'firstName': '',
                                         'lastName': '',
                                         'email':'',
                                         'active':true
                                    });
                                   
                var panel = button.up('panel');
                editor = panel.editingPlugin;   
                editor.cancelEdit();
                this.getCustomersStore().insert(0, customer);
                editor.startEditByPosition({row: 0, column: 2});
            }
                          
    });

Click here for next Chapter

Recommended Reading


7 comments :

  1. Thanks for the document and that helped me greatly. Further; i wanted to add a image(edit icon just to inform user that this field is editable) and it's doing great. The mess starts when i double-click on the field. No doubt the textbox is coming but it holds both image tag and the original value(email in this case). Could you please guide me.

    ReplyDelete


  2. The share your really gives us excitement. Thanks for your sharing. If you feel tired at work or study try to participate in our games to bring the most exciting feeling. Thank you!
    hotmail sign in | red ball game | 192.168.1.1

    ReplyDelete