Use the MVC design pattern of the dojo Grid

Source: Internet
Author: User

To the original author of tribute: http://www.ibm.com/developerworks/cn/web/wa-aj-dojogrid/

Introduction

Dojo is a portable open-source JavaScript toolkit that allows you to quickly build rich client web applications. It contains a wide range of utilities that can be used to build fast-response applications. It also provides many pre-encapsulated out-of-the-box widgets that you can use to immediately start using dojo. However, Dojo does not provide documentation to demonstrate in detail how to use each type of widget, such as the dojo grid. To some extent, Dojo grid is like a micro-spreadsheet that can be presented on a web page. This article guides you through the main functions of the dojo grid from the perspective of Model-View-controller (MVC) design pattern to help you easily understand and master the dojo grid, even if you have never used it before.

MVC is an architecture model used in the software engineering field. The successful use of the model can separate the business logic problem from the user interface, so that developers can freely modify a business logic without affecting other logics. In this mode, the controller processes input events through the user interface and triggers model modifications in the background. The model operates on the application data, and the view uses the model to present the results to the user. This mode is widely used in many frameworks, such as Microsoft? MFC, Java swing, and Java Enterprise Edition. The following sections describe the table features by MVC.

Model

To differentiate the vivid appearance of the raw data from the UI, Dojo grid maintains a data model to store all the raw data that the table will operate on. For example, data of the date/time type is usually stored in milliseconds, rather than in readable formats such as "2009-7-22, therefore, it is easier to construct and convert it to other types of date objects.

Like all MVC widgets, a table has its own data model called data storage. In dojo, almost all widgets that require data storage can use functions such as itemfilereadstore and itemfilewritestore to access universal data storage without using new APIs specific to their data.

Itemfilereadstore is used to read JSON data in a specific format. The dojox project also provides more storage methods such as xmlstore, csvstore, and opmlstore. These storage methods are used to process servers that can output data in the corresponding format.

In dojo grid and many other MVC widgets, all data is usually operated in data storage in the form of an item or item attribute. In this way, you can access data in a standard way, and many widgets can use data at the same time. Listing 1 shows the sample data storage structure used in this article.

Listing 1. Simple data storage structure example
{
Identifier: 'id ',
Label: 'name ',
Items :[
{ID: 0, name: 'Alex ', Manager: True, sex: 'male', age: 30, Date: 1097990400000,
Annualleavetotal: 15, annualleavetaken: 2 },
{ID: 1, name: 'jack', Manager: false, sex: 'male', age: 26, Date: 1184995200000,
Annualleavetotal: 10, annualleavetaken: 3 },
{ID: 2, name: 'Rose ', Manager: True, sex: 'female', age: 40, Date: 894604800000,
Annualleavetotal: 20, annualleavetaken: 4 },
{ID: 3, name: 'wang', Manager: True, sex: 'male', age: 44, Date: 836630400000,
Annualleavetotal: 20, annualleavetaken: 5 },
.....
}

In this example:

Each item has eight attributes.

The ID attribute is a unique identifier.

Data storage can be built in two ways: declared as a tag or constructed programmatically.

Use tags to build data storage

To use tags to build data storage, you must first use JSON files to store all data in an orderly manner (see Listing 2 ). This document uses the data. JSON file ., You can then write the tag in Listing 2 in the HTML file.

Listing 2. Declaring data storage in HTML
<Span dojotype = "dojo. Data. itemfilewritestore" jsid = "mystore"
Url = "data. JSON"> </span>

Next, allocate the storage to the table, as shown in listing 3.

Listing 3. Allocating table data storage
<Table id = "Grid" jsid = "Grid" dojotype = "dojox. Grid. DataGrid" store = "mystore"
Rowselector = "10px">
<Thead>
...
<Thead>
<Table>

Now, when dojo parses the HTML code and constructs the table, it creates a dojo storage object, which will be retrieved from data. obtain data from the JSON file and set table store to "mystore ". Figure 1 shows an example of the generated table.

Figure 1. constructed simple table

Using tags to build table store is simple and quick. However, if data comes from a server and is dynamically organized, you need to build tables and their storage programmatically.

Build Data Storage programmatically

To dynamically construct and modify table store and respond to the server, you must:

Use JavaScript to programmatically organize incoming data into familiar data of dojo.

Create a dojo storage.

Set storage as a table.

The code in Listing 4 constructs a JSON object as a data storage format.

Listing 4. reorganizing data
Generatestoredata: function (/* JSON array */itemlist ){
VaR data = {};
VaR items = [];
For (VAR I = 0; I <itemlist. length; I ++ ){
VaR item = {};
Item ["ID"] = itemlist [I]. ID;
Item ["name"] = itemlist [I]. Name;
Item ["Manger"] = itemlist [I]. ismanger;
Item ["sex"] = itemlist [I]. sex;
Item ["Age"] = itemlist [I]. Age;
Item ["date"] = itemlist [I]. date;
Item ["annualleavetotal"] = itemlist [I]. altotal;
Item ["annualleavetaken"] = itemlist [I]. altaken;
Items. Push (item );
}
Data ["identifier"] = "ID ";
Data ["label"] = "name ";
Data ["items"] = items;
Return data;
}

Next, you can create a storage and set it to a table.

Listing 5. Create and set table store
Dijit. byid ("Grid"). Store = new dojo. Data. itemfilereadstore ({
Data: This. generatestoredata (itemlist)
});

The tables obtained by all these steps are exactly the same as shown in Figure 1.

Query Data Storage

Dojo grid usually stores the entire data source in its data model. However, as the data size increases, this may affect the performance. In fact, when the number of items in the dojo grid storage exceeds a certain number, and if each item has many attributes, the performance of table operations such as sorting, search, and rendering will be significantly reduced.

However, you can improve the performance in some ways. You can write code to allow the server to send limited data to the browser and construct the data into a table data storage, alternatively, you can use or extend the queryreadstore provided by the dojox project to dynamically load data from the server. This method can be used to retrieve data blocks from large data storage on the server.

Listing 6. Use query storage to process large data
<Div dojotype = "dojox. Data. queryreadstore" jsid = "Store" url = "../someservlet"
Requestmethod = "Post"> </div>
 
<Div dojotype = "dojox. Grid. Data. dojodata" jsid = "model" store = "Store"
Sortfields = "[{attribute: 'name', descending: true}]" rowsperpage = "30"> </div>
  
<Div id = "Grid" jsid = "Grid" dojotype = "dojox. Grid. DataGrid" model = "model" structure = "layout"
Rowselector = "10px"> <div>

The dojox project provides many other data storage services for different purposes. Table 1 shows the available storage in dojo and their objectives.

Table 1. Available storage in Dojo

Dojo Storage Purpose
Dojo. Data. itemfilereadstore It is used for read-only storage of JSON data.
Dojo. Data. itemfilewritestore Read/write storage of JSON data.
Dojox. Data. csvstore Read-Only storage of data in CSV format.
Dojox. Data. opmlstore Used for read-only storage of outline processor Markup Language (opml.
Dojox. Data. htmltablestore Read-Only storage of data stored in HTML tables
Dojox. Data. xmlstore Read/write storage for basic XML data
Dojox. Data. flickrstore Reading and storage of queries on flickr.com is an outstanding example of Web Service data storage.
Dojox. Data. flickrreststore Reading and storage of queries on flickr.com is an outstanding example of Web Service data storage. This is a more advanced version of flickrstore.
Dojox. Data. queryreadstore Similar to itemfilereadstore, itemfilereadstore is used for read-only storage of JSON data, but queries the server when each request is received.
Dojox. Data. atomreadstore It is used to read and store atom XML documents.

Custom dojo Data Storage

You can also use the dojo. data API to write custom data storage. Data Access should be divided into several parts, and data storage should use the appropriate API to implement each part.

Dojo. Data. API. Read supports reading data items and their attributes. This also includes searching, sorting, and filtering data items.

Dojo. Data. API. Write supports creating, deleting, and updating data items and their attributes. Not all backend services support modifying data items. In fact, most public services, such as flikr, delicious, and googlemaps, are mainly read-based data providers.

Dojo. Data. API. Identity supports locating and searching projects based on unique project identifiers (if any. Not all data formats have unique identifiers that can be used to find data items.

Dojo. Data. API. Notification allows you to notify listeners of changes to data items in the storage. A basic change event includes creation, deletion, and update. These changes are particularly useful for data storage that regularly polls backend services for data refreshing.

View

In the MVC design mode, the view retrieves application data from the model and presents it to the user. The table provides many functions to simplify rendering changes. In the following sections, I will demonstrate some typical usage and demonstrate the powerful table functions from the perspective of views ..

Use tags to define a table layout

In general, tables can be declared in HTML markup or programmatically defined in JavaScript. Listing 7 provides an advanced structure definition using tags, which generates the display appearance shown in 2.

Listing 7. JavaScript code that uses the tag to define the Layout
<Table id = "Grid" jsid = "Grid" dojotype = "dojox. Grid. DataGrid" store = "mystore"
Rowselector = "10px">
<Thead>
<Tr>
<TH field = "ID" width = "10px"> id </Th>
<TH field = "name"> name </Th>
<TH field = "manager" with = "50px"> is Manager </Th>
<TH field = "sex" width = "50px"> sex </Th>
<TH field = "Age" width = "50px"> age </Th>
<TH field = "date" width = "100px"> on board date </Th>
</Tr>
<Tr>
<TH field = "annualleavetotal" colspan = "3">
Total annual leave days
</Th>
<TH field = "annualleavetaken" colspan = "3">
Annual leave days already taken
</Th>
</Tr>
</Thead>
</Table>

Figure 2. Use tags to define a layout table

Define table layout programmatically

The table structure can also be set programmatically. The structure attribute can specify an object to define the cell structure.

Listing 8. Define the Layout Javascript code programmatically
VaR layout = [{
Name: 'id ',
Field: 'id ',
Width: '10px'
},{
Name: 'name ',
Field: 'name ',
Width: '50px'
},{
Name: 'Is Manager ',
Field: 'manager ',
Width: '100px'
},{
Name: 'sex ',
Field: 'sex ',
Width: '50px'
},{
Name: 'age ',
Field: 'age ',
Width: '50px'
},{
Name: 'On board date ',
Field: 'date ',
Width: '100px'
},{
Name: 'total annual leave days ',
Field: 'annualleavetotal ',
Width: '100px'
},{
Name: 'annual leave days already taken ',
Field: 'annualleavetaken ',
Width: '100px'
}];
 
VaR grid = new dojox. Grid. DataGrid ({
ID: 'grid ',
Store: mystore,
Structure: Layout
}, Dojo. byid ('grid '));

Lock column to disable horizontal scrolling

You can lock a group of columns to prevent them from scrolling horizontally, and allow other columns to continue scrolling. To implement this function, you can use two structures and set the noscroll attribute of one structure to true.

In the example shown in listing 9, two structures are declared. Set the noscroll attribute of the structure of the ID and name columns to true. Then, an array is used to combine the two structures into a layout structure.

Listing 9. Locking the JavaScript code for the ID and name Columns
VaR fixlayout = {
Noscroll: True,
Cells :[{
Name: 'id ',
Field: 'id ',
Width: '10px'
        
},{
Name: 'name ',
Field: 'name ',
Width: '50px'
}]
};
 
VaR mainlayout = {
Onbeforerow: beforerow,
Onafterrow: afterrow,
Cells :[{
Name: 'Is Manager ',
Field: 'manager ',
Width: '200px'
},{
Name: 'sex ',
Field: 'sex ',
Width: '50px'
},{
Name: 'age ',
Field: 'age ',
Width: '50px'
},{
Name: 'On board date ',
Field: 'date ',
Width: '100px ',
},{
Name: 'total annual leave days ',
Field: 'annualleavetotal ',
Width: '100px'
},{
Name: 'annual leave days already taken ',
Field: 'annualleavetaken ',
Width: '100px'
}]
};
 
VaR layout = [fixlayout, mainlayout];

As shown in figure 3, the ID and name columns are locked, but the remaining columns can still scroll horizontally.

Figure 3. Tables with fixed columns

Rows that contain multiple rows of data

A table supports multiple rows of data in a single logical row. You can add the colspan attribute to the layout definition, as shown in listing 10.

Listing 10. Defining JavaScript code for rows containing multiple rows of data
VaR layout = [[{
Name: 'id ',
Field: 'id ',
Width: '10px'
},{
Name: 'name ',
Field: 'name ',
Width: '50px'
},{
Name: 'Is Manager ',
Field: 'manager ',
Width: '100px'
},{
Name: 'sex ',
Field: 'sex ',
Width: '50px'
},{
Name: 'age ',
Field: 'age ',
Width: '50px'
},{
Name: 'On board date ',
Field: 'date ',
Width: '100px'
}], [{
Name: 'total annual leave days ',
Field: 'annualleavetotal ',
Colspan: '2'
},{
Name: 'annual leave days already taken ',
Field: 'annualleavetaken ',
Colspan: '2'
}];

The columns named "total annual leave days" and "annual leave days already taken" are in the same row as the data in other columns.

Figure 4. Table with multiple rows

Table Data Format

You can use a table format function to change the data presentation mode in data storage. This is a core concept of MVC. It can define a data format that conforms to the user's local habits, such as a date, or even construct HTML components, such as check boxes. Listing 11 provides an example.

Listing 11. JavaScript code for formatting table data
VaR dateformatter = function (data, rowindex ){
Return dojo. Date. locale. Format (new date (data ),{
Datepattern: "DD Mmm YYYY ",
Selector: "date ",
Locale: "en"
});
};
 
VaR managerformatter = function (data, rowindex ){
If (data ){
Return "<input type = 'checkbox' checked/> ";
}
Else {
Return "<input type = 'checkbox'/> ";
           
}
};
 
VaR layout = [{
Name: 'id ',
Field: 'id ',
Width: '10px'
},{
Name: 'name ',
Field: 'name ',
Width: '50px'
},{
Name: 'Is Manager ',
Field: 'manager ',
Formatter: managerformatter,
Width: '100px'
},{
Name: 'sex ',
Field: 'sex ',
Width: '50px'
},{
Name: 'age ',
Field: 'age ',
Width: '50px'
},{
Name: 'On board date ',
Field: 'date ',
Width: '100px ',
Formatter: dateformatter
},{
Name: 'total annual leave days ',
Field: 'annualleavetotal ',
Width: '100px'
},{
Name: 'annual leave days already taken ',
Field: 'annualleavetaken ',
Width: '100px'
}];

Figure 5. Table Data Format

Use get Interface

You can use get interface to define other columns outside of data storage to Dynamically Retrieve values. In the above example, I have the "Total annual leave days" and "annual leave days already taken" columns. If you want to know the number of days of annual leave (calculated based on the existing two columns), you can use get interface to search for it dynamically.

I added a new column named "annual leave days left". Its value is "total annual leave days" minus "annual leave days already taken", as shown in listing 12.

Listing 12. JavaScript code using get Interface
Function getleftdays (rowindex, item ){
If (item! = NULL ){
Return item. annualleavetotal-item. annualleavetaken;
}
}
 
 
VaR layout = [{
Name: 'id ',
Field: 'id ',
Width: '10px'
},{
Name: 'name ',
Field: 'name ',
Width: '50px'
},{
Name: 'Is Manager ',
Field: 'manager ',
Formatter: managerformatter,
Width: '100px'
},{
Name: 'sex ',
Field: 'sex ',
Width: '50px'
},{
Name: 'age ',
Field: 'age ',
Width: '50px'
},{
Name: 'On board date ',
Field: 'date ',
Width: '100px ',
Formatter: dateformatter
},{
Name: 'total annual leave days ',
Field: 'annualleavetotal ',
Width: '100px'
},{
Name: 'annual leave days already taken ',
Field: 'annualleavetaken ',
Width: '100px'
},{
Name: 'annual leave days left ',
Get: getleftdays,
Width: '100px'
}];

Figure 6. Use get Interface

Controller

In the MVC design mode, the controller processes and responds to events (usually user operations), and can indirectly call changes in the model. The Controller in Dojo grid has very powerful functions. It provides many methods to customize table behaviors, such as how to process events, how to sort data, and how to filter data.

In the following sections, I will show you how to use and customize controllers in the dojo grid.

Event Processing

Dojo grid has a powerful event processing mechanism, which provides event calling Interfaces Based on Different table elements and event types. For example, it can respond to the Click Event on one row or cell, and it can also respond to the Mouseover event. Therefore, it is useful when you customize the event processing methods to perform specific operations.

I will use oncellclick as an example to demonstrate how to add my own handler on the dojo grid. In this example, I customize this method to display the cell values and the indexes of rows and columns. (See listing 13 ).

Listing 13. JavaScript code for the oncellclick event handler of the custom table
<SCRIPT>
VaR showdetail = function (e ){
VaR value = E. cellnode. firstchild. Data;
Alert ('value: '+ value + "column:" + E. cellindex + "row:" + E. rowindex );
}
       
Dojo. addonload (function (){
Dojo. Connect (grid, "oncellclick", showdetail );
}
</SCRIPT>

First, you need to define the event handler showdetail to display cell details (values, column indexes, and row indexes ). Next, you need to use dojo. Connect to connect the Custom Handler to the oncellclick event. You must perform the same operation in Dojo. addonload, because this method ensures that all the dojo widgets are initialized and available.

When you click a table cell, the application displays an alert window. Figure 7 shows the result.

Figure 7. Table-based Custom Event Handlers

Custom sorting

Dojo GRID provides the basic sorting function based on the column data type. For example, in my example, the ID column is sorted by number, and the name column is sorted by letter.

The sorting function in Dojo grid can also be customized. You can customize sorting behaviors or prevent users from sorting certain columns. If you do not want to sort certain columns, you can use the cansort attribute of dojo grid to specify which columns can be sorted.

Listing 14 shows the JavaScript code to disable the sorting of ID columns.

Listing 14. specifying which columns can be sorted by JavaScript code
<SCRIPT>
Dojo. addonload (function (){
Grid. cansort = function (INDEX ){
If (Index = 1) return false;
Return true;
};
}
</SCRIPT>

The parameter index is the column index of the table, starting from 1. If the cansort function returns false, column sorting is disabled.

In addition to specifying which columns can be sorted, you can also specify how to sort columns. In this example, the name column is used as an example. Figure 8 shows the default sorting behavior of the dojo grid.

Figure 8. Default sorting behavior of dojo Grid

I sort name columns in descending order. Note the last three rows: Victor, Wang, and Vicky. By default, tables are case-sensitive and sorted in ASCII order. Therefore, lowercase letters are placed after uppercase letters. However, such behavior does not comply with software globalization standards. In this case, you need a custom sorting function to support global sorting.

Let's take a look at the JavaScript code in listing 5 and see how to customize the ordering function of the dojo grid.

Listing 15. Sorting function for custom dojo Grid
<SCRIPT>
Dojo. addonload (function (){
Mystore. comparatormap = {};
Mystore. comparatormap ["name"] = function (a, B ){
Return A. localecompare (B );
}
}
</SCRIPT>

The data storage object contains a field named comparatormap. With this field, you can change the sorting behavior. In this example, I define a comparison method for the name column and use localecompare to support global sorting. Figure 9 shows the customized sorting result.

Figure 9. Custom dojo grid sorting Behavior

Filter

Dojo GRID provides a very convenient way to filter data on the client. You can define filtering conditions for a column. Listing 16 shows how to filter tables. Only names starting with the letter A are displayed.
Listing 16. Filtering name Columns

<Div dojotype = "dijit. Form. Button"> Filter Name
<SCRIPT type = "dojo/method" event = "onclick" ARGs = "EVT">
// Filter the name from the data store:
Grid. Filter ({name: "*"});
</SCRIPT>
</Div>

After you click the Filter Name button, the filter result is 10.

Figure 10. Filtered table

Conclusion

This article introduces the main functions of dojo grid through the MVC design pattern. Generally, you can implement a function in multiple ways. For example, to display a date in a table, you can use a string to represent the date in data storage, declare a long, and set the correct format for it in the final display. The first option seems simpler. However, if you want to make the table global, the latter option is better. You are expected to use the MVC design pattern in your own dojo grid project. You will further improve code robustness and reusability.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.