Extjs English Step by Step Phonebook Application

Download as pdf or txt
Download as pdf or txt
You are on page 1of 23

ExtJS Tutorial

ExtJS is a cross-browser JavaScript library, that helps you creating web2.0 applications, using different techniques like AJAX, DHTML and DOM scripting. ExtJS includes various GUI (Graphic User Interface) controls or so called widgets, that can be used in web applications, like Text Field, Text Area, Date Field, List Box, Combo Box, Radio Box, Check Box, HTML Editor, Tree Control, Tab Panel, Toolbars, Flash charts, and maybe the most popular, Grid control. Many of the controls can communicate directly to a server side using AJAX (Asynchronous JavaScript and XML). I will show you how to use ExtJS library in a simple example of a Phonebook application, step by step. Before we start, you need to make sure that you have the latest version of ExtJS 3 library. Currently, the latest version is ExtJS 4 but this tutorial is all about ExtJS 3 version. So, in short, you must have ExtJS 3 library. You can download it from the official web site http://www.sencha.com/products/extjs3/download/. For a server side scripting I am going to use PHP. Of course you can use a different server side scripting language if you want. I will use Netbeans as my IDE (Integrated Development Environment). You can use any text editor you want, like Notepad++; I decided to use Netbeans because it has a nice code formatting. On the server side I will use WAMP server because I need support for PHP and MySQL. As you can see, I am using MySQL database as a storage for our data. In this tutorial I will not talk about server side scripting too much, because I assume that you have the basic knowledge of a PHP or some other server side scripting language.

Step 1 Create Database and Tables


I will use the simple database structure Database Name : Phonebook Table Name: Contacts Here is the Contacts Table structure: Column Name ContactId Phone FirstName LastName Address Column Type Int(10) VarChar(30) VarChar(15) VarChar(15) VarChar(100) Additionally PK, AutoInc

Step 2 Loading core ExtJS


In order to use ExtJS stuff you must load appropriate JavaScript and CSS files.
[code] <!-- include ext-all.css --> <link rel="stylesheet" href="js/ext/resources/css/ext-all.css" /> <!-- include ext-base.js --> <script type="text/javascript" src="js/ext/adapter/ext/ext-base.js"></script> <!-- include ext-all.js --> <script type="text/javascript" src="js/ext/ext-all.js"></script> [/code] /ext/resources/css/ext-all.css

this is the .css file that contains (visual)styles for all ExtJS core

components this is the .js file that contains base ExtJS stuff you need js/ext/ext-all.js this is the .js file that contains core ExtJS logic that you need
"js/ext/adapter/ext/ext-base.js"

So, do not forget to include these files into your HTML page where you want to use ExtJS library. Thats all. You are now ready to use ExtJS. So simple. I will create a small loader, because these files may need some time to load (especially if your internet connection is slow) and I want to show the loading progress to the user (client). You do not have to do this if you dont want, it is just an example of how you can track loading core ExtJS files. After that I am loading my custom .js files MainToolbar.js Grid.js ContactWindow.js Application.js

Again this is not the ExtJS logic, and you do not have to do stuff like this, this is just my way of working with ExtJS. So, enough talking lets look at code.

Index.html
[code]
<html> <head> <title>Phonebook - 1.0 Alpha Programmed in ExtJS by Vladica Savic</title> </head> <body> <div id="loading-mask" style=""> </div> <div id="loading"> <center> <div> <img src="images/ajax-loader.gif" width="32" height="32" style="margin-right: 8px; float: left; vertical-align: top;"/>Phonebook - 1.0 - <a href="http://www.vladicasavic.iz.rs">www.vladicasavic.iz.rs</a><br /> <span id="loading-msg" style="float: left;"> Loading images and styles... </span> </div> </center> </div> <!-- include ExtJS CORE logic --> <!-- include ext-all.css --> <link rel="stylesheet" href="js/ext/resources/css/ext-all.css" /> <!-- my custom loader --> <script type="text/javascript"> document.getElementById('loading-msg').innerHTML = 'Loading API'; </script> <!-- include ext-base.js --> <script type="text/javascript" src="js/ext/adapter/ext/ext-base.js"></script> <!-- my custom loader --> <script type="text/javascript"> document.getElementById('loading-msg').innerHTML = 'Loading ExtJS'; </script> <!-- include ext-all.js --> <script type="text/javascript" src="js/ext/ext-all.js"></script> <!-- my custom loader --> <script type="text/javascript"> document.getElementById('loading-msg').innerHTML = 'Loading Panel...'; </script> <!-- my <script <script <script <script custom .js files --> type="text/javascript" type="text/javascript" type="text/javascript" type="text/javascript" src="js/toolbars/MainToolbar.js"></script> src="js/grids/Grid.js"></script> src="js/windows/ContactWindow.js"></script> src="js/Application.js"></script>

<!-- my custom loader --> <script type="text/javascript"> document.getElementById('loading-msg').innerHTML = 'Launching Application...'; </script> </body> </html>

[/code]

Main Layout
Lets first create a basic application layout. Phonebook application will be a window that contains a toolbar menu with options that implements CRUD (Create Read Update Delete) operations. It will also has central region where we will put a Grid control for displaying our Contacts. First, I will create just a window frame. Later I will add a toolbar menu with described options and a Grid control. All these stuff are described in the Application.js file. Application.js
[code] Ext.namespace('Phonebook'); Ext.onReady(function() { try { document.execCommand('BackgroundImageCache', false, true); } catch (ex) { } Ext.QuickTips.init(); Phonebook.Application = function() { var hideMask = function () { Ext.get('loading').remove(); createMainWindow(); } hideMask.defer(1000); function createMainWindow() { var mainWindow = new Ext.Window({ title: 'Phonebook 1.0 - Programmed in ExtJS by Vladica Savic', width: 500, height: 400, collapsible: true, minimizable: true, maximizable: true, items: [ ] }); mainWindow.show(); }; } (); }); [/code]

As the result you should see the window like this:

Now, we need to create a toolbar menu. This menu shoud have options for all CRUD operations. I will add one additional button for exiting from the phonebook application. My idea is to use Constructors as you will see; The code will be separated into a logical parts, so later on when someone else want to join our project, he could easy understand and implement any changes for the further development.

MainToolbar.js [code]
Ext.namespace('Phonebook'); Phonebook.MainToolbar = function() { var self = this; var action = { AddContact: new Ext.Action({ text: 'Add', handler: addContactHandler, iconCls: 'action-add-contact', scale: 'medium' }), DeleteContact: new Ext.Action({ text: 'Delete', handler: deleteContactHandler, iconCls: 'action-delete-contact', scale: 'medium' }), EditContact: new Ext.Action({ text: 'Edit', handler: editContactHandler, iconCls: 'action-edit-contact', scale: 'medium' }), CloseMainWindow: new Ext.Action({ text: 'Exit', handler: closeMainWindowHandler, iconCls: 'action-exit', scale: 'medium' }) }; function addContactHandler(){ self.fireEvent('AddContactEvent'); } function deleteContactHandler(){ self.fireEvent('DeleteContactEvent'); } function editContactHandler(){ self.fireEvent('EditContactEvent'); } function closeMainWindowHandler(){ self.fireEvent('CloseMainWindowEvent'); } Phonebook.MainToolbar.superclass.constructor.call(this, { items: [ action.AddContact, '-', action.DeleteContact, '-', action.EditContact, '->', action.CloseMainWindow ] });

};

Ext.extend(Phonebook.MainToolbar, Ext.Toolbar, { initComponent: function() { Phonebook.MainToolbar.superclass.initComponent.apply(this, arguments); this.addEvents('AddContactEvent'); this.addEvents('DeleteContactEvent'); this.addEvents('EditContactEvent'); this.addEvents('CloseMainWindowEvent');

});

[/code] Note that we have defined several action objects, described by the text, style, handler. Handler is an java script function that will be executed by calling some of these actions. Also, each of these actions is one button that is presented as an constructor element. On the UI (User Interface) we can separate buttons with '-' separators . Also we can separate element group on the other toolbar side by using '->' separator. This '->' separator will put next toolbar element all the way up the right side of the toolbar. Also, since each of the toolbar button uses appropriate css class to load the desired icon, we must create that css file, include it in our project, and make the appropriate css classes. In our case: 'action-add-contact', 'action-delete-contact', 'action-edit-contact','action-exit'. So, I create my own site.css file where I assign appropriate images to toolbar buttons. You can see how do I do it in code bellow:
<! site.css contains my custom styles --> <link href="css/site.css" rel="stylesheet" type="text/css" />

[CODE]
/* Images for main toolbar buttons */ .action-add-contact { background-image: url(../images/action-add-contact.png) !important; .action-delete-contact { background-image: url(../images/action-delete-contact.png) !important; .action-edit-contact { background-image: url(../images/action-edit-contact.png) !important; .action-exit { background-image: url(../images/action-exit.png) !important; } } } }

[/CODE]

Remark! Make shure the paths and names of icons that you want to load are valid! After adding MainToolbar.js script (before Application.js; this is important) on our Index.html page, we can create toolbar object in Application.js file like this: [CODE]
var mainToolbar = new Phonebook.MainToolbar();

[/CODE] Now we are going to set tbar property of a mainWindow object. This property represents the window toolbar (tbar). [CODE]
var mainWindow= new Ext.Window({ title: 'Phonebook 1.0 - Programmed in ExtJS by Vladica Savic', width: 500, height: 400, collapsible: true, minimizable: true,

maximizable: true, maximized: false, items: [ ], tbar: mainToolbar });

[/CODE] Now when you start application you should get a window like this:

Our application will have one more window which will be used for creating and editing contacts. This window will be defined in a javascript document ContactWindow.js. We need to include this ContactWindow.js file in our Index.html document, again before Application.js ContactWindow.js [CODE]
Ext.namespace('Phonebook'); Phonebook.ContactWindow = function(mode) { var self = this; var windowTitle = (mode == 'edit') ? "Edit contact": "New contact"; var action = { SaveContactInformation: new Ext.Action({ text: 'Save', handler: saveContactInformationHandler }), closeContactWindow: new Ext.Action({ text: 'Close', handler: closeContactWindowHandler }) }; function closeContactWindowHandler(action, e) { self.close(); } function saveContactInformationHandler (action, e) { self.fireEvent('SaveContactInformation'); } Phonebook.ContactWindow.superclass.constructor.call(this, { title: windowTitle, width: 290, height: 290, resizable: false, split: true, modal: true, items: [{ xtype: 'label', style: 'margin: 5;', text: 'First Name:' },{ xtype:'textfield', width: 265, name: 'FirstName', id: 'firstName', style: 'margin: 5px;' },{ xtype: 'label', style: 'margin: 5;', text: 'Last Name:' },{ xtype:'textfield', width: 265, name: 'LastName', id: 'lastName', style: 'margin: 5px;'

},{

xtype: 'label', style: 'margin: 5;', text: 'Address:' xtype:'textarea', name: 'Address', id: 'address', width: 265, style: 'margin: 5px', grow: false, preventScrollbars:true xtype: 'label', style: 'margin: 5;', text: 'Phone:' xtype:'textfield', width: 265, name: 'Phone', id: 'phone', style: 'margin: 5px;'

},{

},{

},{

} ], buttons: [ action.SaveContactInformation, action.closeContactWindow ] }); }; Ext.extend(Phonebook.ContactWindow, Ext.Window, { initComponent: function() { Phonebook.ContactWindow.superclass.initComponent.apply(this, arguments); this.addEvents('SaveContactInformation'); } });

[/CODE]

Since this will be the same object(window) that we will use for creating and editing contacts, we are going to send a mode parameter to function which is used to create this window. The mode parameter represents the working mode creating or editing. Basically it is used as a flag for detecting create or edit operations. Also, we can see that this object contains items objects. In our case labels, text-fields and text-area. These information will be stored in the database.

Here is one example of how you can create item objects. As you can see I am creating the item object in inline facion directly inside items property of the container object [CODE]
{ xtype:'textarea', name: 'Address', id: 'address', width: 265, style: 'margin: 5px', grow: false, preventScrollbars:true

[/CODE] Use xtype property for declaring the item type (textarea in our example), name property for object name, ... Another way of creating item object is to create a separate object and then add this object in containers items property. [CODE]
var someTextAreaObject = Ext.form.TextArea({ name: 'Address', id: 'address', width: 265, style: 'margin: 5px', grow: false, preventScrollbars:true });

[/CODE]

One the most popular ext components is grid component. We will use grid component for displaying all existing contacts and its data. In a Grid.js file we will create the grid: Grid.js [CODE]
Ext.namespace('Phonebook'); Phonebook.ContactsGrid = function() { var pageLimit = 20; var storeRecord = new Ext.data.Record.create([ { name: 'ContactId', type: 'int' }, { name: 'FirstName' }, { name: 'LastName' }, { name: 'Address' }, { name: 'Phone' } ]); var dataStore = new Ext.data.Store({ url: 'ServerSide/Process.php', baseParams: { action: 'getContacts', limit: pageLimit }, reader: new Ext.data.JsonReader( { root: "data", totalProperty: "totalContacts" }, storeRecord ), listeners: { 'loadexception': { fn: function(data) { var responseText = data; if(responseText == '') { Ext.MessageBox.alert('Information', 'There are no contacts in a database.'); } } } } }); Phonebook.ContactsGrid.superclass.constructor.call(this, { title: '', store: dataStore, loadMask: false, border: false, frame: false, stripeRows: true, bbar: new Ext.PagingToolbar({ pageSize: pageLimit, store: dataStore, displayInfo: true, displayMsg: 'Displayed {0} - {1} of {2} contacts', emptyMsg: "0 - 0 of 0" }), sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),

}); };

columns: [ { id: 'firstName', width: 100, header: 'First Name', dataIndex: 'FirstName', sortable: true }, { header: 'Last Name', width: 100, dataIndex: 'LastName', sortable: true }, { header: 'Address', width: 260, dataIndex: 'Address', sortable: true }, { header: 'Phone', width: 100, dataIndex: 'Phone', sortable: true } ]

Ext.extend(Phonebook.ContactsGrid, Ext.grid.GridPanel, { initComponent: function() { Phonebook.ContactsGrid.superclass.initComponent.apply(this, arguments); }, onRender: function() { Phonebook.ContactsGrid.superclass.onRender.apply(this, arguments); } });

[/CODE]

Here we have one dataStore object where we will store data for our grid, basically, data about our contacts. DataRecord is definition of objects contained in dataStore. So DataRecord is just an record of dataStore object. Also, you can see that we are going to get a data from a server in a json format, so we will use JsonReader for reading. Url parameter of a dataStore object represents the server side script which will send a data back to the client. Parameter baseParams defines the arguments that we will send to the server side srcipt. In our example we are sending action parameter, so the server side script will parse this argument and execute appropriate code deppending on the action parameter value. Also, limit parameter will be used to limit the number of data that server side srcipt will send back (this parameter is used in order to avoid needlessly server overloading and somethimes we do not need all the data from the server also). RowSelectionModel parameter is set to singleSelect which means that only one row can be selected in a grid. You can change this if you want, but in our example we are going to use single selection mode. Parameter bbar represents bottom bar. Another characteristics of the grid is column definition. In addition to the standard layout that is used in our case, it is possible to join so-called renderer which provides that certain fields(cells) can be represented different on the UI. For example we could have a grid cell which is combobox, checkbox, datefield, color picker, and custom html but its real value is text, or json, or something else.

You should understand this in a way of converting one value into onother. You can define your own custom template object like this: [CODE]
var customTemplateObject = new Ext.XTemplate( '<div>Some custom HTML</div>', '<p>...adjust it as you like!</p>' );

[/CODE]
Now if you start application you should see the window like this one:

In Application.js we will create objects for the main layout Application.js [CODE]
Ext.namespace('Phonebook'); Ext.onReady(function() { try { document.execCommand('BackgroundImageCache', false, true); } catch (ex) { } Ext.QuickTips.init(); Phonebook.Application = function() { var hideMask = function () { Ext.get('loading').remove(); createMainWindow (); } hideMask.defer(1000); // Overriding standard button text and other ext controls // for localization // ------------------------------------------------------Ext.MessageBox.buttonText = { ok : "OK", cancel : "Cancel", yes : "Yes", no : "No" }; Ext.apply(Ext.PagingToolbar.prototype, { beforePageText : "Page", afterPageText : "from {0}", firstText : "First page", prevText : "Previous page", nextText : "Next page", lastText : "Last page", refreshText : "Refresh" }); Ext.apply(Ext.grid.GridView.prototype, { sortAscText : "Sort ascending", sortDescText : "Sort descending", columnsText : "Columns" }); //----------------------------------------------------function createMainWindow() { var mainToolbar = new Phonebook.MainToolbar(); var contactsGrid = new Phonebook.ContactsGrid(); contactsGrid.getStore().load({ params:{ start: 0, limit: 20 } }); mainToolbar.on( 'CloseMainWindowEvent', function(e, target) { closeMainWindow ();

}); mainToolbar.on('AddContactEvent',function(e, target) { addContact (); }); mainToolbar.on('DeleteContactEvent',function(e, target) { deleteContact (); }); mainToolbar.on('EditContactEvent',function(e, target) { editContact (); }); var mainWindow = new Ext.Window({ title : 'Phonebook 1.0 - Programmed in ExtJS by Vladica Savic', width : 600, height : 400, layout :'fit', collapsible : true, maximizable : true, maximized : false, items: [ contactsGrid ], tbar : mainToolbar }); mainWindow.show(); function closeMainWindowAction(buttonId, text, opt) { if(buttonId=="yes") { mainWindow.close(); } } function closeMainWindow (){ Ext.Msg.show({ title : 'Exit', msg : 'Are you sure you want to exit the application?', buttons : Ext.Msg.YESNO, fn : closeMainWindowAction, width : 300 }); } function saveContactInformation(mode){ var var var var firstName = Ext.get('firstName').dom.value; lastName = Ext.get('lastName').dom.value; address = Ext.get('address').dom.value; phone = Ext.get('phone').dom.value;

if(mode=='edit'){ // Edit selected contact editContactAction (firstName, lastName, address, phone); }else{ // Add new contact (create) addContactAction (firstName, lastName, address, phone); } } function deleteContact(){ // Check if there is at least one contact selected to delete if (contactsGrid.getSelectionModel().hasSelection()) {

Ext.Msg.show({ title : 'Delete', msg : 'Are you sure you want to delete this contact?', buttons : Ext.Msg.YESNO, fn : deleteContactAction, width : 320 }); }else{ Ext.Msg.show({ title :'Error', msg :'Please select contact to delete!', buttons : Ext.Msg.OK }); } } function addContact (){ var contactWindow = new Phonebook.ContactWindow ("add"); contactWindow.show(); contactWindow.on('SaveContactInformation',function(e, target) { saveContactInformation("add"); contactWindow.close(); }); } function editContact (){ if (contactsGrid.getSelectionModel().hasSelection()) { var contactWindow = new Phonebook.ContactWindow ("edit"); contactWindow.show(); // auto-fill fields with data from a selected contact Ext.get('firstName').dom.value = contactsGrid.getSelectionModel().getSelections()[0].data.FirstName; Ext.get('lastName').dom.value = contactsGrid.getSelectionModel().getSelections() [0].data.LastName; Ext.get('address').dom.value = contactsGrid.getSelectionModel().getSelections() [0].data.Address; Ext.get('phone').dom.value = contactsGrid.getSelectionModel().getSelections() [0].data.Phone; //...set some value to some object //Ext.get('idElementa').dom.value = 'some value; //...different way //Ext.get('idElementa').set({ // value: 'some value //}); contactWindow.on('SaveContactInformation',function(e, target) { saveContactInformation ("edit"); contactWindow.close(); }); }else{ Ext.Msg.show({ title :'Error', msg :'Please select contact to edit.', buttons : Ext.Msg.OK }); }

function editContactAction (firstName, lastName, address, phone) { contactsGrid.getGridEl().mask('Saving in progress...'); var contactId = contactsGrid.getSelectionModel().getSelections()[0].data.ContactId; Ext.Ajax.request({ url: 'ServerSide/Process.php', method: 'POST', params: { action : 'editContact', contactId : contactId, firstName : firstName, lastName : lastName, address : address, phone : phone }, success: function(response, options) { contactsGrid.getStore().load({ params:{ start: 0, limit: 20 } }); contactsGrid.getGridEl().unmask(true); } }); } function addContactAction (firstName, lastName, address, phone){ contactsGrid.getGridEl().mask('Entering new data...'); Ext.Ajax.request({ url: 'ServerSide/Process.php', method: 'POST', params: { action : 'addContact', firstName : firstName, lastName : lastName, address : address, phone : phone }, success: function(response, options) { contactsGrid.getStore().load({ params:{ start: 0, limit: 20 } }); contactsGrid.getGridEl().unmask(true); } }); } function deleteContactAction(buttonId, text, opt){ if(buttonId=="yes") { contactsGrid.getGridEl().mask('Refresing ...'); Ext.Ajax.request({ url: 'ServerSide/Process.php', method: 'POST', params: { action : 'deleteContact', contactId : contactsGrid.getSelectionModel().getSelections() [0].data.ContactId },

}); } } } (); }); }

success: function(response, options) { contactsGrid.getStore().load({ params:{ start: 0, limit: 20 } }); contactsGrid.getGridEl().unmask(true); }

[/CODE] Here I will describe Ext.Ajax.request method. [CODE]


Ext.Ajax.request({ url: 'ServerSideScript.php', method: 'POST', params: { //Additional parameters to send to the server side script }, success: function(response, options) { // ajax callback function // here you can manipulate with the server response }

[/CODE]

});

Also, there is a part for interaction with the user. Depending on action somethimes is usefull to notify the user about action state like: Working..., Finished, Canceled, ... Asking from a user to confirm object delete is also a practise. Ext has interesting dialogs you can use to implement these features. Here are some examples for dialogs:
Ext.Msg.show({ title : 'Some custom title', msg : 'Some custom text which will be shown to the user', buttons : Ext.Msg.YESNO, //Possible values: Ext.Msg.OK, Ext.Msg.YESNOCANCEL ... fn width : yourCustomHandler, //Function called when user clicks a dialog button : 320

[CODE]

});

[/CODE] If you want to detect which button user clicked, you can use buttonId parameter in a fn function like:
yourCustomHandler(buttonId){ // some code to handle buttonId }

Server Side PHP


All server side code that we are going to need for a CRUD(Create Read Update Delete) operations is implemented in a Process.php script. Process.php [CODE]
<?php /* * code for CRUD operations with contacts */ if(isset($_POST["action"])) { //Change connection parameters if you need $connection = mysql_connect("localhost", "root", "") or die (mysql_error ()); $database = mysql_select_db ("phonebook") or die (mysql_error ()); $action = $_POST["action"]; switch ($action) { case "getContacts": { $sql = mysql_query ("SELECT * FROM contacts") or die (mysql_error()); $total = mysql_num_rows($sql); $sqlResult = mysql_query ( "SELECT * FROM contacts ORDER BY contactId LIMIT ".$_POST['start'].", ". $_POST['limit']."") or die (mysql_error ()); $data = array(); while ($contact=mysql_fetch_object($sqlResult)) { $data [] = $contact; } echo '({"Total contacts":"'.$total.'","data":'.json_encode($data).'})'; } break; case "addContact": { $firstName = $_POST["firstName"]; $lastName = $_POST["lastName"]; $address = $_POST["address"]; $phone = $_POST["phone"]; $sqlAddContact = 'INSERT INTO contacts ( firstName, lastName, address, phone) VALUES ( "'.$firstName.'", "'.$lastName.'", "'.$address.'", "'.$phone.'")'; mysql_query("SET NAMES utf8"); echo $sqlAddContact; if(!mysql_query($sqlAddContact)) { die('Error creating contact. Error details: '.mysql_error()); } } break; case "editContact": { $contactId = $_POST["contactId"]; $firstName = $_POST["firstName"]; $lastName = $_POST["lastName"]; $address = $_POST["address"]; $phone = $_POST["phone"]; $sqlEditContact = 'UPDATE contacts SET firstName = "'.$firstName.'",

lastName = "'.$lastName.'", address = "'.$address.'", phone = "'.$phone.'" WHERE contactId = "'.$contactId.'"'; echo $sqlEditContact; mysql_query("SET NAMES utf8"); if(!mysql_query($sqlEditContact)) { die('Error editing contact! Error details: '.mysql_error()); } } break; case "deleteContact": { $contactId = $_POST["contactId"]; $sqlDeleteContact = 'DELETE FROM contacts WHERE contactId = "'.$contactId.'"'; echo $sqlDeleteContact; mysql_query("SET NAMES utf8"); if(!mysql_query($sqlDeleteContact)) { die('Error deleting contact! Error details: '.mysql_error()); } } break; } } ?>

[/CODE] As you can see, because this script contains all application logic for CRUD operations, I added parameter action so using this action parameter our script isnt whole executed, just the separate logic parts (Create Edit Delete) of it will be executed.

Index
Namespace is abstract container for a logic groups or unique identifiers or symbols. Idenitifier defined in a namespace is associated just with that namespace. The same identifier name can be used in different namespaces. In programming, the scope is a place where all values and expressions are ssociated. Different programming languages has different scope types. Scope type determines which entities the scope contains. Usually, scope is used to define a information visibility. Event Response to a user action or source state change.

Author
To all readers who have survived to the end of this document All the best Special thanks to my friends: Dalibor Aleksov for translating this tutorial, and eljo Bankovi for code testing. If you have any questions or suggestions you can contact me at: Vladica Savi [email protected]

You might also like