Creating Register and Login Form Using EXTJS and CodeIgniter

June 2nd, 2010 by aditia rahman / 95 Comments  

     

Like another tutorial this post will create the basic form login and register using Extjs and Codeigniter, and I want to mix my previous post about Codeigniter Session Library, Extjs Unique Field Validation and using Statusbar in Extjs Window.

1. Setting up the database

Using phpmyadmin in XAMPP I create the database named “ci_extjs_login”, and create simple “users” table, here below is the sql code that I generated from phpmyadmin, for more advance database modelling you can use mysql workbench.

CREATE TABLE  `ci_extjs_login`.`users` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 100 ) NOT NULL ,
`password` VARCHAR( 100 ) NOT NULL ,
`email` VARCHAR( 100 ) NOT NULL
) ENGINE = MYISAM ;

2. Setting up the Codeigniter

If you not have the copy of codeigniter you can download the latest from here here, then copy the extracted file in your server folder, (here I’m using the default XAMPP htdocs), first setting the databse connection, open the file “system/application/config/database.php”, set the hostname, username, password, and database name (for username & password I’m using the XAMPP default)

$db['default']['hostname'] = "localhost";
$db['default']['username'] = "root";
$db['default']['password'] = "";
$db['default']['database'] = "ci_extjs_login";

Setting the config file, open file “system/application/config/config.php”, my base_url setting is like this (set the value to “http://localhost/ci_extjs_login/”)

$config['base_url'] = "http://localhost/ci_extjs_login/";

Setting the autoload file, open file “system/application/config/autoload.php”, in this file set the default loaded helpers and libraries to be loaded by the application

$autoload['libraries'] = array('database', 'session', 'my_usession');

As you can see above, the “database” and “session”, are the default codeigniter library, for “my_usession” i’m using my own library it’s pretty simple to implement, to see more you can read my previous post, next to load the url codeigniter helper, this will help when you linking a page to the server in Extjs.

$autoload['helper'] = array('url');

Setting the route file, open file “system/application/config/routes.php”, change the default controller to “user” even though in this step we haven’t create the file yet

$route['default_controller'] = "user";

3. Adding the Extjs file to in Codeigniter

I usually create the separated folder from system in Codeigniter, create “assets” folder to put all images, css and javascript file, so you can put all the Extjs file in the js folder, as you can see on the image in the right. All Extjs file placed in the “ext” folder and the “ext_plugins” folder is the where I usually placed the plugins. You can see “nbproject” folder, this is the auto generated folder when you are developing project using netbeans, you can remove it if you are in the production state. The next is to include the Extjs file in every html header, now create view file in codeigniter here “system/application/views/header.php” and my code is like this

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>assets/js/ext/resources/css/ext-all.css"/>

    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/ext/adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/ext/ext-all.js"></script>
    <script type="text/javascript">
        var BASE_URL = '<?php echo base_url(); ?>' + 'index.php/';
        var BASE_PATH = '<?php echo base_url(); ?>';
        Ext.onReady(function() {
            Ext.QuickTips.init();
            Ext.BLANK_IMAGE_URL = BASE_PATH + 'assets/js/ext/resources/images/default/s.gif';
            Ext.form.Field.prototype.msgTarget = 'side';
        });
    </script>

    <style>
    body {
        background:#7F99BE;
    }
    #header {
        border-bottom:1px solid #666;
        background:#1E4176;
        padding:5px;
        color:#fff;
        font-size:20px;
        font-weight:bold;
        font-family:'Lucida Grande', Arial, Sans;
    }
    </style>
    <title><?php echo $title; ?></title>
</head>
<body>

As you can see above I’m using the Codeigniter url helper, base_url() to locate the Extjs file, the defined variable in javascript “BASE_URL” and “BASE_PATH” is useful when requesting server location, you can see on the next step. Now create file for login screen in “system/application/views/user/login.php” and add this code

<?php $this->load->view('header'); ?>

<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>assets/js/ext_plugins/statusbar/css/statusbar.css"/>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/ext_plugins/statusbar/StatusBar.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/form_validation.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/form_login.js"></script>

<?php $this->load->view('footer'); ?>

The status bar plugin you can copied from Extjs default example located in “assets/js/ext/examples/ux/statusbar” copy all the files inside this folder, actually you can directly link to that folder, but for me it easier to read the plugin that I used in the folder hierarchy. We have not create the two javascript file “form_validation.js” and “form_login.js” yet, we’ll create it on the next step, but I always wanted a footer file on the view so create file “system/application/views/footer.php” and the code is as simple as this (for this project just to closing the html and body tag)

</body>
</html>

Now create the javascript file, in this file we will create two from in the same file, which mean one page, two Extjs windows and two Extjs forms (login and register). Create file in “assets/js/form_login.js” insert this code

Ext.onReady(function() {

    /* 01. Start The Form Register Component */

    // 01. Form Register
	var formRegister = new Ext.FormPanel({
		frame: false, border: false, buttonAlign: 'center',
		url: BASE_URL + 'user/ext_register', method: 'POST', id: 'frmRegister',
		bodyStyle: 'padding:10px 10px 15px 15px;background:#dfe8f6;',
		width: 300, labelWidth: 150,
		items: [{
			xtype: 'textfield',
			fieldLabel: 'Username',
			name: 'username',
			id: 'regUsername',
			allowBlank: false,
            vtype: 'uniqueusername'
		}, {
			xtype: 'textfield',
			fieldLabel: 'Password',
			name: 'password',
			allowBlank: false,
			inputType: 'password',
            vtype: 'passwordlength',
            id: 'pass1'
		}, {
			xtype: 'textfield',
			fieldLabel: 'Confirm Password',
			name: 'cpassword',
			allowBlank: false,
			inputType: 'password',
            id: 'pass2',
            initialPassField: 'pass1',
            vtype: 'password'
		}, {
			xtype: 'textfield',
			fieldLabel: 'Email',
            id: 'regEmail',
			name: 'email',
			vtype:'uniqueemail',
			allowBlank: false,
            validationEvent: ''
		}
		],
		buttons: [
			{ text: 'Register', handler: fnRegister },
			{ text: 'Reset', handler: function() {
					formRegister.getForm().reset();
				}
			}
		]
	});

    function fnRegister() {
        Ext.getCmp('frmRegister').on({
            beforeaction: function() {
                if (formRegister.getForm().isValid()) {
                    Ext.getCmp('winRegister').body.mask();
                    Ext.getCmp('winLogin').body.mask();
                    Ext.getCmp('sbWinRegister').showBusy();
                }
            }
        });
        formRegister.getForm().submit({
            success: function() {
                formRegister.getForm().reset();
                Ext.getCmp('sbWinRegister').setStatus({
                    text: 'Registration Success',
                    iconCls: 'x-status-saved'
                });
                Ext.getCmp('winRegister').body.unmask();
                Ext.getCmp('winLogin').body.unmask();
            }
        });
    }

    // 01. Window Register
	var winRegister = new Ext.Window({
		title: 'CI Extjs &mdash; User Register',
        id: 'winRegister',
		layout: 'fit',
		width: 350,
		height: 210,
		y: 120,
		resizable: false,
		closable: false,
		items: [formRegister],
        bbar: new Ext.ux.StatusBar({
            text: 'Ready',
            id: 'sbWinRegister'
        })
	});

	winRegister.show();

    /* 02. Start The Form Login Component */

    // 02. Form Login
    var formLogin = new Ext.FormPanel({
		frame: false, border: false, buttonAlign: 'center',
		url: BASE_URL + 'user/ext_login', method: 'POST', id: 'frmLogin',
		bodyStyle: 'padding:10px 10px 15px 15px;background:#dfe8f6;',
		width: 300, labelWidth: 150,
		items: [{
			xtype: 'textfield',
			fieldLabel: 'Username',
			name: 'username',
			id: 'logUsername',
			allowBlank: false
		}, {
			xtype: 'textfield',
			fieldLabel: 'Password',
			name: 'password',
            id: 'logPassword',
			allowBlank: false,
			inputType: 'password'
		}
		],
		buttons: [
			{ text: 'Login', handler: fnLogin },
			{ text: 'Reset', handler: function() {
					formLogin.getForm().reset();
				}
			}
		]
	});

    function fnLogin() {
        Ext.getCmp('frmLogin').on({
            beforeaction: function() {
                if (formLogin.getForm().isValid()) {
                    Ext.getCmp('winRegister').body.mask();
                    Ext.getCmp('winLogin').body.mask();
                    Ext.getCmp('sbWinLogin').showBusy();
                }
            }
        });
        formLogin.getForm().submit({
           success: function() {
               window.location = BASE_URL;
           },
           failure: function(form, action) {
               Ext.getCmp('winRegister').body.unmask();
               Ext.getCmp('winLogin').body.unmask();
               if (action.failureType == 'server') {
                    obj = Ext.util.JSON.decode(action.response.responseText);
                    Ext.getCmp('sbWinLogin').setStatus({
                        text: obj.errors.reason,
                        iconCls: 'x-status-error'
                    });
                } else {
                    if (formLogin.getForm().isValid()) {
                        Ext.getCmp('sbWinLogin').setStatus({
                            text: 'Authentication server is unreachable',
                            iconCls: 'x-status-error'
                        });
                    } else {
                        Ext.getCmp('sbWinLogin').setStatus({
                            text: 'Something error in form !',
                            iconCls: 'x-status-error'
                        });
                    }
                }
           }
        });
    }

    // 02. Window Login
	var winLogin = new Ext.Window({
		title: 'CI Extjs &mdash; User Login',
        id: 'winLogin',
		layout: 'fit',
		width: 350,
		height: 160,
		y: 340,
		resizable: false,
		closable: false,
		items: [formLogin],
        bbar: new Ext.ux.StatusBar({
            text: 'Ready',
            id: 'sbWinLogin'
        })
	});

	winLogin.show();
});

Now for the custom validation file I’m using the unique field validation from my previous post and modified a little bit, although is not perfect but still can used in here, so create file “assets/js/form_validation.js” and the code is

/* Custom Unique Username Validation
 * Used in 01. Form Register */

var usernameErrLength = 'Username minimum 4 character !';
var usernameErrUnique = 'Username already in use !';
var usernameSuccess = 'Username avaliable';
var emailErrFormat = 'Email not valid !';
var emailErrUnique = 'Email already in use !';
var emailSuccess = 'Email valid & avaliable';

Ext.apply(Ext.form.VTypes, {
    uniqueusernameMask : /[a-z0-9_\.\-@\+]/i,
	uniqueusername : function(val) {
        if (val.length < 4) {
            Ext.apply(Ext.form.VTypes, {
                uniqueusernameText: usernameErrLength
            });
            return false;
        } else {
            Ext.Ajax.request({
                url: BASE_URL + 'user/ext_is_unique_username',
                method: 'POST',
                params: 'username=' + val,
                success: function(o) {
                    if (o.responseText == 0) {
                        resetUsernameValidator(false);
                        Ext.apply(Ext.form.VTypes, {
                            uniqueusernameText: usernameErrUnique
                        });
                        return false;
                    } else {
                        resetUsernameValidator(true);
                    }
                }
            });
            return true;
        }
	},
	uniqueusernameText : usernameErrUnique,

    uniqueemailMask : /[a-z0-9_\.\-@\+]/i,
    uniqueemail : function(val) {
        var uniqueemail = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/;
        if (uniqueemail.test(val)) {
            Ext.Ajax.request({
                url: BASE_URL + 'user/ext_is_unique_email',
                method: 'POST',
                params: 'email=' + val,
                success: function(o) {
                    if (o.responseText == 0) {
                        resetEmailValidator(false);
                        Ext.apply(Ext.form.VTypes, {
                            uniqueemailText: emailErrUnique
                        });
                    } else {
                        resetEmailValidator(true);
                    }
                }
            });
            return true;
        } else {
            return false;
        }

    },
    uniqueemailText : emailErrFormat,

    password : function(val, field) {
        if (field.initialPassField) {
            var pwd = Ext.getCmp(field.initialPassField);
            return (val == pwd.getValue());
        }
        return true;
    },
    passwordText : 'Passwords do not match',

    passwordlength : function(val) {
        if (val.length < 5) {
            return false;
        } else {
            return true;
        }
    },
    passwordlengthText : 'Password minimum 5 character'
});

function resetUsernameValidator(is_error) {
	Ext.apply(Ext.form.VTypes, {
		uniqueusername : function(val) {
            if (val.length < 4) {
                Ext.apply(Ext.form.VTypes, {
                    uniqueusernameText: usernameErrLength
                });
                return false;
            } else {
                Ext.Ajax.request({
                    url: BASE_URL + 'user/ext_is_unique_username',
                    method: 'POST',
                    params: 'username=' + val,
                    success: function(o) {
                        if (o.responseText == 0) {
                            resetUsernameValidator(false);
                        } else {
                            resetUsernameValidator(true);
                        }
                    }
                });
                return is_error;
            }
		}
	});
}

function resetEmailValidator(value) {
    Ext.apply(Ext.form.VTypes, {
        uniqueemail : function(val) {
            var uniqueemail = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/;
            if (uniqueemail.test(val)) {
                Ext.Ajax.request({
                    url: BASE_URL + 'user/ext_is_unique_email',
                    method: 'POST',
                    params: 'email=' + val,
                    success: function(o) {
                        if (o.responseText == 0) {
                            resetEmailValidator(false);
                            Ext.apply(Ext.form.VTypes, {
                                uniqueemailText: emailErrUnique
                            });
                        } else {
                            resetEmailValidator(true);
                        }
                    }
                });
            } else {
                return false;
            }
            return (value);
        }
    });
}

The last file in views is index which is called when user is authenticated in “system/application/views/user/index.php”, here I’m using my last project layout using Extjs and I can’t explain more about this, if you want simple layout just html and php that would be fine, or if you want follow my step you can separate the javascript file from the php file like the way from previous step

<?php $this->load->view('header'); ?>

<script type="text/javascript">
    var layout_west1 = new Ext.tree.TreePanel({
    region: 'north', title: 'Menus', height: 250, bodyStyle: 'margin-bottom:6px;',
    autoScroll: true, enableDD: false, rootVisible: false, id: 'treePanel',
    root: {
        text: 'Menu',
        expanded: true,
        nodeType: 'async',
        children: [{
            text: 'Menu 1',
            expanded: true,
            children: [{
                text: 'Menu 1.1',
                leaf: true
            }, {
                text: 'Menu 1.2',
                expanded: true,
                children: [{
                    text: 'Menu 1.2.1',
                    leaf: true
                }, {
                    text: 'Menu 1.2.2',
                    leaf: true
                }, {
                    text: 'Menu 1.2.3',
                    leaf: true
                }]
            }]
        }, {
            text: 'Menu 2',
            expanded: true,
            children: [{
                text: 'Menu 2.1',
                leaf: true
            }, {
                text: 'Menu 2.2',
                leaf: true
            }]
        }, {
            text: 'Logout',
            id: 'logout',
            icon: BASE_PATH + 'assets/img/icons/minus-circle.png',
            leaf: true
        }]
    },
    listeners: {
        click: function(n) {
            switch (n.id) {
                case 'logout':
                    do_logout();
                    break;
            }
        }
    }
});

var layout_west2 = new Ext.Panel({
	region: 'center', margin: '10 0 0 0', autoScroll: true,
	bodyStyle: 'padding:10px;background:#eee;font-family:"Lucida Grande"',
	html: '<p style="padding:20px;text-align:center;color:#666;font-size:14px;border:1px dotted #999;background:#fff;">\n\
            <img src="public/img/btn-left.jpg"/><br/> CodeIgniter - Extjs <br/><span style="font-size:11px;">Simple Login Screen</span></p>'
});

var tab_center = new Ext.TabPanel({
    xtype: 'tabpanel', resizeTabs: false, minTabWidth: 115, tabWidth: 135,
    enableTabScroll: true, layoutOnTabChange: true, border: false,
    activeItem: 'tab_welcome', autoDestroy: false,
    items: [
        { xtype: 'panel', id: 'tab_welcome', bodyStyle: 'padding:10px', title: 'Welcome' }
    ]
});

var tbCenter = new Ext.Toolbar({
    items: ['->', {
        icon: BASE_PATH + 'assets/img/icons/minus-circle.png',
        text: 'Logout',
        handler: do_logout
    }]
});

var layout_center = new Ext.Panel({
    id: 'content-panel', region: 'center', layout: 'card', margins: '0 5 5 0',
    activeItem: 0, border: true, tbar: tbCenter, items: [tab_center]
});

var layout_main = new Ext.Viewport({
	layout: 'border', renderTo: Ext.getBody(),
	items: [
        { region: 'north', autoHeight: true, height: 100, border: false,
            html: '<div id="header">CodeIgniter - Extjs<span style="font-size:12px;">Simple Login Screen</span></div>',
            margins: '0 0 5 0', style: 'border-bottom: 4px solid #4c72a4;' },
        { region: 'west', baseCls: 'x-plain', xtype: 'panel', autoHeight: true,
            width: 180, border: false,
            split: true, margins: '0 0 0 5', items: [layout_west1, layout_west2]
        }, layout_center]
});

function do_logout() {
    Ext.Ajax.request({
        url: BASE_URL + 'user/ext_logout',
        method: 'POST',
        success: function(xhr) {
            window.location = BASE_URL + 'user/login';
        }
    });
}

layout_main.show();
</script>

<?php $this->load->view('footer'); ?>

4. Create controller

Create the controller file user.php in “system/application/controllers/user.php”

<?php

class User extends Controller {

    public function __construct()
    {
        parent::Controller();
    }

    public function index()
    {
        if ($this->my_usession->logged_in)
        {
            $data['title'] = 'User Index';
            $this->load->view('user/index', $data);
        }
        else
        {
            redirect('user/login');
        }
    }

    public function login()
    {
        if ($this->my_usession->logged_in)
        {
            redirect('user/index');
        }
        else
        {
            $data['title'] = 'User Login';
            $this->load->view('user/login', $data);
        }
    }

    public function ext_is_unique_username()
    {
        $cond = array('username' => $_POST['username']);
        $query = $this->db->get_where('users', $cond);
        if ($query->num_rows() != 0)
        {
            echo 0;
        }
        else
        {
            echo 1;
        }
    }

    public function ext_is_unique_email()
    {
        $cond = array('email' => $_POST['email']);
        $query = $this->db->get_where('users', $cond);
        if ($query->num_rows() != 0)
        {
            echo 0;
        }
        else
        {
            echo 1;
        }
    }

    public function ext_logout()
    {
        $this->my_usession->unset_userdata("user_id");
        echo "{success:true}";
    }

    public function ext_login()
    {
        $cond = array(
            'username' => $_POST['username'],
            'password' => $_POST['password']
        );
        $query = $this->db->get_where('users', $cond);
        if ($query->num_rows() != 0)
        {
            $row = $query->row();
            $this->my_usession->set_userdata('user_id', $row->id);
            $this->my_usession->set_userdata('username', $row->username);
            echo "{success:true}";
        }
        else
        {
            echo "{success:false, errors: { reason: 'User not found !' }}";
        }
    }

    public function ext_register()
    {
        $data = array(
            'username' => $_POST['username'],
            'password' => $_POST['password'],
            'email' => $_POST['email']
        );
        $this->db->insert('users', $data);

        echo "{success:true}";
    }

}

The final result should look like this

default login and register form in “http://localhost/ci_extjs_login/index.php/user/login”

default index layout in “http://localhost/ci_extjs_login/index.php/”

Like always I provide the source to be downloaded but, not included the Extjs file, you have to download yourself from here.

DOWNLOAD SOURCE

        submit to reddit Delicious

95 Comments Leave a Comment Subscribe RSS

Leave a Comment