CRUD using CodeIgniter and EXTJS Grid Part 2

July 12th, 2010 by aditia rahman / 27 Comments  

     

This post is continuation of the part 1, in part 1 we already created the Extjs grid with pagination and load the store grid from the database, in this part we will add the save, edit and delete feature to that grid, and for make it easier it will use the editor grid.

First Edit The View ( in “application/views/user/index.php” )

We will use the editorGrid, one of them should be editable on the combobox field and the value is fetched from the database, so we create country store component and set like the code below (in this step we haven’t created the method to get all countries. it described in the controller section).

var strCountries = new Ext.data.Store({
    reader: new Ext.data.JsonReader({
        fields: ['id', 'country_name'], root: 'countries'
    }),
    proxy: new Ext.data.HttpProxy({
        url: BASE_URL + 'user/ext_get_all_countries', method: 'POST'
    })
});

Now edit the toolbar so it can manipulate the grid and the data inside it, the “Add” button is to creating new data by adding the new row on the grid, and the user has to double click the new row to be edited. “Save Selected” button is to save the selected row button, it means user have to click the button and select the row to be saved, means can save multiple row at the save time. Last is “Delete” button that can be delete multiple row.

var tbUsers = new Ext.Toolbar({
    items:[{
        text: 'Add',
        icon: BASE_ICONS + 'user_add.png',
        handler: function() {
            var User = gridUsers.getStore().recordType;
            var u = new User({
                fullname: 'New Full Name',
                email: 'New Email',
                country: 'Water Seven',
                occupation: 'Occupation',
                birthdate: '1899-10-10'
            });
            gridUsers.stopEditing();
            strUsers.insert(0, u);
            gridUsers.startEditing(0, 0);
        }
    }, '-', {
        text: 'Save Selected',
        disabled: true,
        id: 'btnSave',
        icon: BASE_ICONS + 'save.gif',
        handler: updateUsers
    }, '-', {
        text: 'Delete',
        icon: BASE_ICONS + 'user_delete.png',
        handler: deleteUsers
    }]
});

function updateUsers() {
    var sm = gridUsers.getSelectionModel();
    var sel = sm.getSelections();
    var data = '';
    for (i = 0; i<sel.length; i++) {
        data = data + sel[i].get('id') + ';'
                + sel[i].get('fullname')
                + ';' + sel[i].get('email')
                + ';' + sel[i].get('country_id')
                + ';' + sel[i].get('occupation')
                + ';' + sel[i].get('birthdate')
                + '||';
    }
    Ext.Ajax.request({
        url: BASE_URL + 'user/ext_update',
        method: 'POST',
        params: { postdata: data }
    });
    strUsers.load();
}

function deleteUsers() {
    Ext.Msg.show({
        title: 'Confirm',
        msg: 'Delete Selected Users ?',
        buttons: Ext.Msg.YESNO,
        fn: function(btn) {
            if (btn == 'yes') {
                var sm = gridUsers.getSelectionModel();
                var sel = sm.getSelections();
                var data = '';
                for (i = 0; i<sel.length; i++) {
                    data = data + sel[i].get('id') + ';';
                }
                Ext.Ajax.request({
                    url: BASE_URL + 'user/ext_delete',
                    method: 'POST',
                    params: { postdata: data }
                });
                strUsers.load();
            }
        }
    });
}

And don’t forget to change the grid panel component from Ext.grid.GridPanel toExt.grid.EditorGridPanel and add the editor property to each column like this one.

columns: [
    cbGrid, {
        header: "Fullname",
        dataIndex: 'fullname',
        width: 180,
        editor: new Ext.form.TextField({
            allowBlank: false
        })
    }, {
        header: "Email",
        dataIndex: 'email',
        width: 180,
        editor: new Ext.form.TextField({
            allowBlank: false,
            vtype: 'email'
        })
    }, {
        header: "Country",
        dataIndex: 'country_name',
        width: 120,
        editor: new Ext.form.ComboBox({
            id: 'cbCountry',
            triggerAction: 'all',
            store: strCountries,
            valueField: 'id',
            displayField: 'country_name'
        })
    }, {
        header: "Occupation",
        dataIndex: 'occupation',
        width: 120,
        editor: new Ext.form.TextField({
            allowBlank: false
        })
    }, {
        header: "Birth",
        dataIndex: 'birthdate',
        width: 80,
        renderer : Ext.util.Format.dateRenderer('d/m/Y'),
        editor: new Ext.form.DateField({
            format: 'd/m/Y',
            allowBlank: false
        })
    }
]

Second Edit The Controller (in “application/controllers/user.php”)

Add new function inside the controller to get all the countries, add user, edit user and delete user. The first snippet below is function to get all the countries data, ideally I always create another controller because it accessing the different table and this country data have “has one” relationship to user controller, but in this post to make it fast I put that function in the same controller.

public function ext_get_all_countries()
{
    $this->db->order_by('country_name');
    $query = $this->db->get('countries');
    $json = "{'countries':[";
    foreach($query->result() as $data)
    {
        $json .= '{"id":"'.$data->id .
                '", country_name:"' . $data->country_name.'"},';
    }
    $json .= "]}";
    echo $json;
}

And next is adding function for adding new data and edit existing data, you can see below there are looping when inserting the data, it because from the Extjs grid send multiple value, so I need to break down in array using explode function ini PHP, and there some converting date format cause the Extjs given the different date format when converting to string than mysql.

public function ext_update()
{
    /* ex ext date: 1899-11-27T00:00:00
       mysql : YYYY-MM-DD */

    $records = explode('||', $_POST['postdata']);

    foreach ($records as $row)
    {
        $field = explode(';', $row);

        $birthdate = substr($field[5], 0, 10);

        $data = array(
            'fullname' => $field[1],
            'email' => $field[2],
            'occupation' => $field[4],
            'birthdate' => $birthdate
        );

        if (is_numeric($field[3]))
        {
            $data['country_id'] = $field[3];
        }
        else
        {
            $data['country_id'] = 1;
        }

        if (is_numeric($field[0]))
        {
            $this->db->where('id', $field[0]);
            $this->db->update('users', $data);
        }
        else
        {
            $this->db->insert('users', $data);
        }
    }
}

And the last is to delete all selected row from the grid, it is the way from the above snippet, the id that we want to deleted
consolidated in one string, and php explode it to an array

public function ext_delete()
{
    $records = explode(';', $_POST['postdata']);
    foreach($records as $id)
    {
        $this->db->where('id', $id);
        $this->db->delete('users');
    }
}

Well that for the part two, most feature have already been added for the CRUD grid, for part just for finishing I may add a quaick search field on the grid, and here’s below the complete code from this post.

Download Source

        submit to reddit Delicious

27 Comments Leave a Comment Subscribe RSS

  • ikhsan says:

    thank boss.. makasih tutorialnya. tapi di coba di firefox tanggal lahir nya NaN/…, kalo di opera sama chrome sebagian aja yg NaN/..nya. sebabnya kenapa ya ? masalah browser atau versi phpnya ?

    • NaN pada date field kemungkinan karena nilai date nya tidak ada atau nilai nya “0000-00-00″ pada database

      • reimhart says:

        sir can you please translate your answer in english. coz, i think that’s the error i’d encountered. when I select a date on the from the interface, it post NaNNaNNaN..but when I edit the date on the phpmyadmin. the date in the interface is in correct format.. tnx in advance for you response.. :)

        • NaN value, probably because of the date value is empty on database or the value is “0000-00-00″

          • reimhart says:

            tnx sir..
            can i ask a favor.. how can create a Ext program where in when i click the row of data there will be a window that will going to pop up. and the pop up window contains form where in the user can edit the record.. please help me.. thank sir.. GODbless.

          • you have to add “rowclick” event handler on the grid,
            then use “getSelectionModel” to grab all the value on the clicked row and send it to each form field value inside the window,

            hope that giving a little enlightenment…

    • Leidy says:

      A wonderful job. Super helpful ifnrmoaiton.

  • reimhart says:

    is it possible if I use Ext.Window in a function? I’m trying to add a handler to the add button where in everytime the user click the add button, the ne window will appear so they can now add what theyeant to add.. tnx

    • yup I think it possible but make sure you create the function inside Ext.onReady(function)

      • reimhart says:

        Sir can I send to you my code, and try to look at it.
        //this code is created by the ext designer separately
        Ext.onReady(function() {
        Ext.QuickTips.init();
        var cmp1 = new InhabitantsMaster({
        renderTo: Ext.getBody()
        });
        cmp1.show();
        });

        the designer created 4 different files and the file containing the design has no Ext.onREady function.. the code aleady starts with this:

        InhabitantsMasterUi = Ext.extend(Ext.Window, {
        title: ‘Barangay Automated System and Inhabitants Database – Barangay Looc’,
        width: 960,
        height: 580,
        layout: ‘border’,
        hideBorders: true,
        closable: false,
        y: 10,
        resizable: false,
        initComponent: function() {
        this.tbar = {
        xtype: ‘toolbar’,
        buttonAlign: ‘right’,
        collapsible: true,
        items: [
        ….
        ….
        ….

  • clustersblue says:

    Sir why is it that when I add this line “$this->load->view(‘user_view’);” (user_view = my user view page) to the function below. The json data gets displayed in the browser not in the grid instead. But when I remove that line and let the grid be displayed in the main view page the result is perfectly ok. What I want is to click “User” from the menu in the main view page before the grid gets displayed.

    function user_view()

    $query = $this->db->get(‘users’);
    $results = $this->db->count_all(‘users’);
    $jdata = array();
    foreach ($query->result() as $row)
    {
    $jdata[] = $row;
    }
    echo ‘{success:true,results:’. $results .
    ‘,rows:’.json_encode($jdata).’}';
    $this->load->view(‘user_view’);

    }

    Btw, thanks for having this tutorial I found it very easy to follow.

    • of course if you load the view it will render the data in json format the user_view template
      if you want to do that make the separate function

      this output code below only to be consumed by Store component
      echo ‘{success:true,results:’. $results .
      ‘,rows:’.json_encode($jdata).’}’;

  • vdthutech says:

    thanks for share. this is example great but i cant not add birthday.
    u format date (d-m-Y) but database (Y-m-d). thanks

    • sorry for late answer, I try to figure it out too….
      but so far I remember the extjs date format send in the format like “1899-11-27T00:00:00″ but when I try it again it became like this “Wed Nov 15 1899 00:00:00 GMT-0800 (Pacific Standard Time)”

      the fastest way to fix it change the update users function it became like this

      function updateUsers() {
      var sm = gridUsers.getSelectionModel();
      var sel = sm.getSelections();
      var data = ”;
      for (i = 0; i var dt = new Date(sel[i].get(‘birthdate’));
      data = data + sel[i].get(‘id’) + ‘;’
      + sel[i].get(‘fullname’)
      + ‘;’ + sel[i].get(‘email’)
      + ‘;’ + sel[i].get(‘country_id’)
      + ‘;’ + sel[i].get(‘occupation’)
      + ‘;’ + dt.format(‘Y-m-d’)
      + ‘||’;
      }
      Ext.Ajax.request({
      url: BASE_URL + ‘user/ext_update’,
      method: ‘POST’,
      params: { postdata: data }
      });
      strUsers.load();
      }

  • Damon says:

    Have you had any issues with updating more then 1 row at a time. My code which is almost exactly the same as yours works for the most part but only on a single update. If I choose more then 1 row it only updates the last row changed. Any thoughts?

    Thanks

  • ronny says:

    mas numpang tanya.. itu yg combo box begitu selesai milih isinya kok yg keluar id-nya ya? bukan displayfieldnya?

    jadi pertama kali halaman di load emang display fieldnya : “Drum Island” tapi begitu aku mau milih “Fuschia Village” setelah itu kok yg keluar id-nya (yaitu : 4) ?

    kenapa ya? mohon pencerahannya..

  • varrick says:

    thank you for your codes ,it is so excellent,I use it very well.
    However,this code display the datebase data in a single form,we use this code to receive the render.Actually,I designed a border layout that split int five parts ,”north”,”south”,”west”,”east”,”center”,and I want to put the result in the “center” part.Do you know what I mean??
    how to do it?
    thank you very much!

  • varrick says:

    and my codes follows:
    var viewport = new Ext.Viewport
    (
    {
    layout:’border’,
    items:
    [
    {
    region: 'north',
    contentEl: 'north-div',
    height: 20,
    bodyStyle: 'background-color:#BBCCEE;'
    },
    {
    region: 'south',
    contentEl: 'south-div',
    height: 20,
    bodyStyle: 'background-color:#BBCCEE;'
    },
    {
    region:'west',
    width:350,
    title:"menu",
    layout:"accordion",
    layoutConfig:
    {
    titleCollapse:true,
    animate:true,
    activeOnTop:false
    },
    collapsible:true,
    items:
    [
    {title:"budget data",html:"element1"},
    {title:"budget formula",html:"element2"},
    {title:"budget requiment",html:"element3"}
    ]
    },
    {
    region: ‘center’,
    split: true,
    border: true,
    layout: ‘border’,
    items: [gridUsers]
    }
    ]
    }
    );
    I want put the results in the ‘center’ region,how to render the form?

  • duant says:

    Thanks for share, this is great but i have error on my firebug when i click add
    the error “gridUsers.startEditing is not a function” and the my browser firefox crash.. would you help me?

  • Yazid Erman says:

    Thank you Rahman for this fantastic article!
    But in this part you have forgotten to talk about adding a Listener to the grid, when editing fields nothing enable the save button!

Leave a Comment