amd in dojo and beyond

50
AMD in Dojo and beyond By Karthick S

Upload: thimba

Post on 23-Feb-2016

81 views

Category:

Documents


0 download

DESCRIPTION

AMD in Dojo and beyond. By Karthick S. Agenda. Dojo fundamentals Introduction to AMD AMD Benefits AMD Development Strategies - Module vs Widget Use Case Using Dijit Widgets Creation of custom widgets Grids and Stores. JavaScript Pre-requisites. Objects Prototypal Inheritance - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: AMD in Dojo and beyond

AMD in Dojo and beyond

By Karthick S

Page 2: AMD in Dojo and beyond

Agenda Dojo fundamentals Introduction to AMD AMD Benefits AMD Development Strategies - Module vs

Widget Use Case Using Dijit Widgets Creation of custom widgets Grids and Stores

Page 3: AMD in Dojo and beyond

JavaScript Pre-requisites Objects Prototypal

Inheritance Closures Callbacks Anonymous functions Prototypes Variable Hoisting Bind, Call and Apply

Page 4: AMD in Dojo and beyond

Why Dojo ? Support for industry standard AMD across the

toolkit Field proven performance of Enterprise Web

Apps Comprehensive Dijit library Flexible to write custom widgets Backing of enterprise bigwigs like IBM, AOL,

and Sun Early adopters of Deferreds and Promises,

Aspects, Client-side pubsub, Offline storage etc

Lots of community packages like grid, xstyle, etc

Page 5: AMD in Dojo and beyond

What is AMD ? Stands for Asynchronous Module Definition Born out of CommonJS and inspired by Dojo

XHR+eval Load ONLY the needed modules

asynchronously Also can load non-AMD plugins like HTML,

JSON, etc Supported from Dojo v1.7 onwards https://github.com/amdjs/amdjs-api/wiki/AMD

Page 6: AMD in Dojo and beyond

Benefits of AMD Say goodbye to globals - AMD provides better

encapsulation Can load and manage 3rd party packages Loads the modules only once and caches

them Better reusability and maintainability Baseless Dojo Supports cross domain loading of JS modules Better minification and portability

Page 7: AMD in Dojo and beyond

AMD APIs

requiredefine

Page 8: AMD in Dojo and beyond

AMD Code Structure dojoLib/dojo dojoLib/dijit dojoLib/dojox dojoLib/dgrid dojoLib/<your-custom-package>/<your-

custom-modules>

e.g.: dojoLib/myApp/myModuleOne

Dojo Library -> Package -> Module/Widget

Page 9: AMD in Dojo and beyond

AMD Code Structure - Contd Dojo comes organized into packages. Packages are collections of modules. Modules are nothing but individual JS files with

define API Modules have 1:1 mapping with the JS files

Page 10: AMD in Dojo and beyond

Dojo Code Sample – Before and After AMDdojo.ready(function(){var myButton = dojo.byId("myButton”);

Before AMD - >dojo.connect(myButton, "onclick", function(evt){ dojo.style(myDiv, "backgroundColor", "blue");});});

require(["dojo/on", "dojo/dom", "dojo/dom-style", "dojo/domReady!"], function(on, dom, domStyle, mouse) {

var myButton = dom.byId("myButton”); After AMD - > on(myButton, "click", function(evt){

domStyle.set(myDiv, "backgroundColor", "blue"); });});

Page 11: AMD in Dojo and beyond

AMD Constructs and Concepts In the Dojo 1.6 and before, dojo.js is loaded

with base API like ready, connect, style, etc. AMD uses “base-less” dojo, i.e. none of the

APIs are loaded by default. Load them whenever we need to use them

using require Wrap the JavaScript code into modules using

define Create custom widgets using define, declare

and new

Page 12: AMD in Dojo and beyond

Using Modules Using require() API.

Syntaxrequire(<module-identifiers-array>, <anonymous-callback-

function>);Argument 1 - DependenciesArgument 2 - Callback Function

Examplerequire([“myPkg/myModule”,

“dojo/dom”, ”dojo/domReady!],

function(myModule,dom){myModule.initApp();

dom.byId(“testDiv”).innerHTML=“AMD is the way to go!”; });

Page 13: AMD in Dojo and beyond

Using Modules – contd.Module Identifier Mappings to the path of the individual JS file(.js). We can specify relative paths as well(like ./) We need to specify all the dependencies here

Callback Function An anonymous function which will be called back, after

loading the dependencies specified in the moduleID array. Arguments are the returned objects of the loaded modules The moduleIDs and the argsList should be in the same

order Special plugins like domReady! don’t return any object

Page 14: AMD in Dojo and beyond

Popular APIs dojo/on - Event handling dojo/dom - DOM manipulations dojo/query - Advanced CSS Selectors dojo/topic - Event publish/subscribe dojo/aspect - Aspect oriented programming

(AOP) dijit/registry - Widget manipulations dojo/_base/fx - Base effects dojo/_base/array - Array manipulations

Page 15: AMD in Dojo and beyond

Dojo Plugins Extend the AMD Loader to provide special

functionalities They do not return any object when included in

require All the plugin module identifiers will end or have

exclamation point (!) Exclamation point is used to indicate process , to

the loader Popular plugins are

“dojo/text!” “dojo/domReady!” “dojo/il8n!”

Page 16: AMD in Dojo and beyond

Dojo Plugins Extend the AMD Loader to provide special

functionalities They do not return any object when included in

require All the plugin module identifiers will end or have

exclamation point (!) Exclamation point is used to indicate process , to

the loader Popular plugins are

“dojo/text!” “dojo/domReady!” “dojo/il8n!”

Page 17: AMD in Dojo and beyond

Example: dojo/text Loads the content of the file into a string object Replaces dojo.cache Used to load the template HTML in widgets

require([“dojo/text!./names.txt”, “dojo/domReady!”], function(names){

var names = names.split(“\n”);console.log(“Names loaded=“,

names.length);});

Page 18: AMD in Dojo and beyond

Defining Modules Use the define() API Code is resolved only when needed.

Syntaxdefine(<module-identifiers-array>, <anonymous-callback-function>);Argument 1 - Dependencies for the moduleArgument 2 - Factory Function - returns an object/value

ExampleFile should -> ”<baseURL>/myPkg/myModule.js”

define([“dojo/dom”],function(dom){return {moduleName: “Test Module”,initApp: function(){dom.byId(‘testDiv’).innerHTML = “Success”;}};});

Page 19: AMD in Dojo and beyond

Dojo 1.6 and before - Using DataGriddojo.require("dojox.grid.DataGrid");dojo.require("dojo.data.ItemFileWriteStore");var grid, store;dojo.ready(function(){store = new dojo.data.ItemFileWriteStore({url: “employees.json”});grid = new dojox.grid.DataGrid({store: store,query: { id: "*" },structure: [{ name: "First Name", field: "first", width: "84px" },{ name: "Last Name", field: "last", width: "84px" },{ name: “Company”, field: “company”, width: "70px" },{ name: “Department”, field: “dept”, width: "70px" },{ name: “Salary”, field: “salary”, width: "60px" }}, "grid"); grid.startup();});

Page 20: AMD in Dojo and beyond

Dojo 1.7 and after - Using DataGridvar grid, dataStore, store;require(["dojox/grid/DataGrid”, "dojo/store/Memory“, "dojo/data/ObjectStore”,

"dojo/_base/xhr”, "dojo/domReady!"], function(DataGrid, Memory, ObjectStore,xhr){xhr.get({url: "employees.json",handleAs: "json"}).then(function(data){store = new Memory({ data: data.items });dataStore = new ObjectStore({ objectStore: store }); grid = new DataGrid({store: dataStore,query: { id: "*" },structure: [{ name: "First Name", field: "first", width: "84px" },{ name: "Last Name", field: "last", width: "84px" },{ name: “Company”, field: “company”, width: "70px" }, { name: “Department”, field:

“dept”, width: "70px" }, ]}, "grid"); grid.startup();});});

Page 21: AMD in Dojo and beyond

Widget Creation declare

SyntaxArg1 - Class/Widget name - OptionalArg2 - Subclass array - Subclasses are called Mixins in DojoArg3 - Class Object

Example

Without AMDdojo.provide(“myPkg.myWidget”);

dojo.require(“dijit._WidgetBase”);dojo.require(“dijit._TemplatedMixin”);

dojo.declare(“myPkg.myWidget”,[dijit._WidgetBase, dijit._TemplatedMixin], {templateString: dojo.cache(“myPkg”, “templates/myWidget.html”);

});

Page 22: AMD in Dojo and beyond

Widget Creation - With AMDdefine([ "dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/text!./templates/myWidget.html"], function(declare, _WidgetBase, _TemplatedMixin, template) { return declare([_WidgetBase, _TemplatedMixin], { templateString: template }); });

Page 23: AMD in Dojo and beyond

Widget Lifecycle All dojo widgets extend the base class,

diiit_WidgetBase Optionally extend dijit_templatedMixin if we

need template or layout for the widget All widgets have a set of lifecycle methods to

them These lifecycle methods are your access to

write custom logic

this.inherited(arguments); - To call the superclass overridden method

Page 24: AMD in Dojo and beyond

Widget Lifecycle Methods constructor - Initialization code.

parameters are mixed into the widget instance

postMixInProperties - Before DOM rendering and creation of DOM nodes. Add or change the instance properties.

buildRendering -dijit._Templated takes care.The template is fetched/read, nodes created and events hooked up during buildRendering. The end result is assigned to this.domNode.

Setters are called

postCreate -Widget has been rendered on the DOM, except for its child widgets. Sizing operations should be done here.

Startup - Called after parsing and creation of child widgets has completed. If the widget does JS sizing, then startup() should call resize(), which does the sizing.

destroy

Page 25: AMD in Dojo and beyond

The Dijit Collection Context, popup, and dropdown menus Form element replacements like buttons, combo boxes,

checkboxes, radio buttons, and text boxes Date and time selection widgets WYSIWYG Editor Horizontal and Vertical Sliders Progress Bars Tabs and Accordions Tree Structures (including Drag and Drop) Dialogs and Tooltips Layout widgets with slide controls and splitters

Page 26: AMD in Dojo and beyond

Requiring Proper Modules and Resources It comes bundled with four supported themes: ->  nihilo, soria, tundra, and claro

 Each theme contains images and CSS files CSS files must be explicitly included into each HTML page:

<style type="text/css">    @import “//ajax.googleapis.com/ajax/libs/dojo/1.8/dojo/resources/dojo.css"; @import //ajax.googleapis.com/ajax/libs/dojo/1.8/dijit/themes/claro/claro.css";</style>

<body class="claro">

Page 27: AMD in Dojo and beyond

dojoConfig dojoConfig

dojoConfig = {    isDebug:true,    async:true}

Note: parseOnLoad was a common property in djConfig, but this is no longer recommended. See information about the parser below.

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.8/dojo/dojo.js"    data-dojo-config="isDebug:true, async:true" type="text/javascript"></script>

<body class="claro">     <button data-dojo-type='dijit/form/Button'>Clicky</button> </body>

Page 28: AMD in Dojo and beyond

dojo/parser We need to load dojo/parser and explicitly tell it to parse. 

After the DOM is ready of course. The AMD way to determine this is with the dojo/domReady plugin. AMD is instructed that the loaded dependency is a plugin with an exclamation point, such as: dojo/domReady!.

<body class="claro">    <button data-dojo-type='dijit/form/Button'>Clicky</button>    <script>        require([            'dojo/parser', “dijit/form/Button”,            'dojo/domReady!'        ], function(parser){            parser.parse(); // tell dojo to check the DOM for widgets        });    </script></body>

Page 29: AMD in Dojo and beyond

Require Dijit widgets AMD Loader is asynchronous and smart enough to

find and load un-required modules.

But Widget should be required explicitly, to get maximum performance from your application,

AMD and Dojo require that you explicitly define the modules and dependencies you want to use in your application. 

Page 30: AMD in Dojo and beyond

Creating Widgets The Basic select Element

<select name="character" id="character">    <option value="">Select a character</option>    <option value="Leonard">Dr. Leonard Leakey Hofstadter</option>    <option value="Sheldon" selected="selected">Dr. Sheldon Lee Cooper</option>    <option value="Rajesh">Dr. Rajesh Ramayan Koothrappali</option>    <option value="Howard">Howard Joel Wolowitz</option></select>

 dijit/form/FilteringSelect

Page 31: AMD in Dojo and beyond

Creating Widgets Declarative way

<select name="character" id="characterNode"    data-dojo-type="dijit/form/FilteringSelect"    data-dojo-props='autoComplete:true, pageSize:10' >    <option value="">Select a character</option>    <option value="Leonard">Dr. Leonard Leakey Hofstadter</option>    <option value="Sheldon" selected="selected">Dr. Sheldon Lee Cooper</option>    <option value="Rajesh">Dr. Rajesh Ramayan Koothrappali</option>    <option value="Howard">Howard Joel Wolowitz</option></select>

 When we call parser.parse(), Dojo will find this element and instantiate and initialize the widget.

Page 32: AMD in Dojo and beyond

Creating Widgets Programmatic Method

 require([    'dijit/form/FilteringSelect',    'dojo/domReady!'], function(FilteringSelect){     var filteringSelect = new FilteringSelect({        autoComplete: true,        pageSize: 10    },'characterNode'); });

  dojo/parser was removed from the list of dependencies, as it’s not needed for programmatic instantiation of widgets.

Page 33: AMD in Dojo and beyond

Creating More Widgetsrequire([    'dijit/form/FilteringSelect',    'dijit/form/DateTextBox',    'dijit/form/Textbox',    'dijit/form/Textarea',    'dijit/form/Checkbox',    'dijit/form/RadioButton',    'dojo/domReady!'], function(FilteringSelect, DateTextBox, Textbox, Textarea, Checkbox, RadioButton){     var filteringSelect = new FilteringSelect({        autoComplete: true,        pageSize: 10    },'characterNode');     var input = new Textbox({/*options*/},'myInputNode');    var textarea = new Textarea({/*options*/},'myTextareaNode');    var mySelect = new FilteringSelect({/*options*/},'mySelectNode');    var date = new DateTextBox({/*options*/},'myDateNode');     var checkbox = new CheckBox({/*options*/},'myCheckboxNode');    var radio1 = new RadioButton({/*options*/},'myRadio1Node');});

Page 34: AMD in Dojo and beyond

Accessing Dijit Widgets and their Properties  Dijit has its own dijit/registry.byId method which retrieves the Dijit widget

registered with the ID specified.

If the element to be made a Dijit has an ID, the widget ID will be that same value. If the source element doesn’t have an ID attribute, a widget ID will be generated. 

require([    'dojo/parser',    'dijit/registry',    'dijit/form/FilteringSelect',    'dojo/domReady!'], function(parser, registry, FilteringSelect){    parser.parse();    var filteringSelect = registry.byId('characterNode');    console.log('filteringSelect', filteringSelect);});

Page 35: AMD in Dojo and beyond

Getter and setters If we wanted to access the pageSize property for which the Dijit

widget was created from, we would access it with a Dijit getter:

var pageSize = registry.byId('characterNode').get('pageSize'); // returns 10

If we wanted to change the pageSize for the widget, we would code:

registry.byId('characterNode').set('pageSize',20); //now pageSize is 20

Page 36: AMD in Dojo and beyond

Listening to Widget Events Dijit widgets use dojo/on method to listen to DOM events on the given

widget:

filteringSelect.on('change', function(value){     console.log('value', value); });

It’s important to note that those are DOM events. If you wish to listen to a widget method, you should use dojo/aspect:

require([    'dojo/aspect'    // other deps...], function(aspect){    aspect.after(filteringSelect, 'validate', function(value){        console.log('validate', value);    });});

Page 37: AMD in Dojo and beyond

Dojo Object Stores new data store API called Dojo Object Store. This new store API is based on the HTML5 IndexedDB object store API  simplify and ease the interaction and construction of Dojo stores. This new API follows HTTP/REST naming conventions   is compatible with the dojox.storage providers (for local storage, cookie

storage, and WebSQL storage), Separate UI from data concerns Dojo Object Store API is an interface between different data consumers to

different data producers. Dojo core comes with two key implementations that are commonly needed: 

dojo/store/Memory and dojo/store/JsonRest.

Page 38: AMD in Dojo and beyond

dojo/store/Memory This is a very simple in-memory store. This is highly useful for quickly creating a store, particularly for smaller

datasets. A Memory store can be created by simply providing a plain array of objects

as the data source for this store, and then you can start querying and interacting with the store

The Memory store is a synchronous store, which means it directly returns values, making it very easy to use.

var product = productStore.get("slinky");var someData = [ {id:1, name:"One"}, {id:2, name:"Two"} ]; store = new dojo.store.Memory({data: someData}); store.get(1) store.query({name:"One"}) store.query(function(object){ return object.id > 1; }) store.put({id:3, name:"Three"}); store.remove(3);

Page 39: AMD in Dojo and beyond

dojo/store/JsonRest dojo/store/JsonRest is a lightweight object store implementation of an

HTTP-based (RFC 2616) client with RESTful data interaction capabilities. This store implements the new Dojo Object Store API. JsonRest provides full read, write, and notification capabilities through

standards based HTTP/REST interaction with the server using GET, PUT, POST, and DELETE commands.

This data store allows you to communicate with server side database/persistent data storage using the Dojo Data API with JavaScript and efficiently handles create, read, update, and delete (CRUD) operations

require(["dojo/store/JsonRest"], function(JsonRestStore){

var store = new JsonRestStore({target: "/Table/" }); store.get(3).then(function(object){}); store.query("foo=bar").then(function(results){}); store.put({ foo: "bar" }, { id: 3 }); // store the object with the given identity store.remove(3); // delete the object});

Page 40: AMD in Dojo and beyond

Object Store API Methods get(id) - This will trigger a GET request to {target}{id}.

query(query, options) - This will trigger a GET request to {target}{query}. If query is an object, it will be serialized using dojo.objectToQuery. If query is a string, it is appended to the URL as-is. If options includes a sort property, it will be serialized as a query parameter as well; see Sortingfor more information.

remove(id) - This will trigger a DELETE request to {target}{id}.

put(object, options) - If object includes an identity property, or options includes an id, this will trigger a PUT request to {target}{id} with the request body being the provided object serialized as JSON. If no identity is provided, then a POST request is made to the store’s target URL (no id appended) with the object as the body. If the options.incremental property is true, then a POST request is made to {target}{id} with the object as the body. You may also include an options.overwrite property. If overwrite is set to true, then an If-Match: * header is included. If overwrite is set to false, then an If-None-Match: * header is included.

add(object, options) - This behaves exactly like put(object, options), except that options.overwrite is set to false, indicating that a new object must be created.

Page 41: AMD in Dojo and beyond

dojo.store.Observable dojo.store.Observable is an object store wrapper that adds support for notification of data

changes to query result sets. The query result sets returned from a Observable store will include a observe function that can be

used to monitor for changes.  The observe function provides indication of the previous and new index values of changed objects to properly

update result arrays. The result sets returned from store.query() calls from a Observable store will have a observe method. The

observe method has the following signature: resultSet.observe(listener); The listener function is called with following arguments: listener(object, removedFrom, insertedInto);

store = dojo.store.Observable(new dojo.store.Memory({data: someData}));var results = store.query({rating:5});// do something with the initial result setresults.forEach(insertRow);var observeHandle = results.observe(function(object, removedFrom, insertedInto){ if(removedFrom > -1){ // existing object removed removeRow(removedFrom); }}); store.put({rating: 5, id: 3}); store.remove(2);observeHandle.cancel();

Page 42: AMD in Dojo and beyond

dojo.store.Cache dojo.store.Cache is a object store wrapper for caching data from one store in another store. This store

follows the Dojo Object Store API. The Cache store provides caching capabilities for stores. The Cache store takes two stores, a master store and

caching store. The master store is considered the data authority, all modifications go to the master store, and when data is

not available in the cache, it is retrieved from the master store. The caching store is used to record cached data from master store. Doing get() and query() call results are

added to the cache (unless they don’t meet provided criteria), but only get() uses the cache, whereas query() uses the master store.

If you want to a query to come from the cache, directly call query() on the caching store. Data modifications are also mirrored in the caching store. A typical usage of dojo.store.Cache would be to use a JsonRest store as the master store, and a Memory store as the caching store.

restStore = new dojo.store.JsonRest(...); memoryStore = new dojo.store.Memory(); store = new dojo.store.Cache(restStore, memoryStore); store.get(1) -> Returns the object with an id of 1 by making a GET request store.get(1) -> Returns the object, using the local memory cache store.put({id:2, name:"two"}) -> Stores the object in both master and cache store store.get(2) -> Returns the object, using the local memory cache

Page 43: AMD in Dojo and beyond

Introduction to the DataGrid The DataGrid is the central component of many applications due to its effective and usable

presentation of tabular data. In this tutorial we will look at how to define a grid's layout and discuss the scrolling mechanism the DataGrid uses.

dojox/grid/DataGrid As you probably guessed, the DataGrid is made up of several different parts. At the highest level, a DataGrid is made up of views. Views break the DataGrid up into sections and render the header andcontent for each section. Headers and contents contain rows (although the header only contains one row) which are populated by sub-

rows of cells.   To define how a DataGrid will look, we will be passing different objects and arrays to the structure property of

the DataGrid constructor.  Cell Definition object

name: the string to use in the header cell field: the name of the field of the data record to display width: a string containing the CSS width (with units) of the column hidden: a boolean that when true will hide the column

Page 44: AMD in Dojo and beyond

Introduction to the DataGrid The DataGrid is the central component of many applications due to its effective and usable

presentation of tabular data. In this tutorial we will look at how to define a grid's layout and discuss the scrolling mechanism the DataGrid uses.

dojox/grid/DataGrid As you probably guessed, the DataGrid is made up of several different parts. At the highest level, a DataGrid is made up of views. Views break the DataGrid up into sections and render the header andcontent for each section. Headers and contents contain rows (although the header only contains one row) which are populated by sub-

rows of cells.   To define how a DataGrid will look, we will be passing different objects and arrays to the structure property of

the DataGrid constructor.  Cell Definition object

name: the string to use in the header cell field: the name of the field of the data record to display width: a string containing the CSS width (with units) of the column hidden: a boolean that when true will hide the column

Page 45: AMD in Dojo and beyond

DataGrid SubRowgrid = new DataGrid({    store: store,    query: { id: "*" },    structure: [        [            { name: "First Name", field: "first", width: "84px", rowSpan: 2 },            { name: "Last Name", field: "last", width: "84px", rowSpan: 2 },            { name: "Bats", field: "bats", width: "70px", rowSpan: 2 },            { name: "Throws", field: "throws", width: "70px", rowSpan: 2 },            { name: "G", field: "totalG", width: "60px" },            { name: "AB", field: "totalAB", width: "60px" },            { name: "R", field: "totalR", width: "60px" },            { name: "RBI", field: "totalRBI", width: "60px" },            { name: "BB", field: "totalBB", width: "60px" },            { name: "K", field: "totalK", width: "60px" }        ],[            { name: "Games as Batter", field: "totalGAB", colSpan: 2 },            { name: "H", field: "totalH" },            { name: "2B", field: "total2B" },            { name: "3B", field: "total3B" },            { name: "HR", field: "totalHR" }        ]    ]}, "grid");

Page 46: AMD in Dojo and beyond

DataGrid Views We've made it a little easier to view our data, however once you scroll to the right you can't see whose

records you're looking at. By defining a view definition, we can lock sections of columns from scrolling left and right. A view definition is an object with some specific properties set on it:

cells: an array or an array of arrays of cell definitions noscroll: a boolean that when true will prevent the view from scrolling horizontally width: a string specifying the CSS width of the view — this is only needed when your cells are defined with

relative widths like percentages

Page 47: AMD in Dojo and beyond

DataGrid Viewsgrid = new DataGrid({    store: store,    query: { id: "*" },    structure: [        {            noscroll: true,            cells: [                { name: "First Name", field: "first", width: "84px" },                { name: "Last Name", field: "last", width: "84px" }            ]        },{            cells: [                [                    { name: "Bats", field: "bats", width: "70px", rowSpan: 2 },                    { name: "Throws", field: "throws", width: "70px", rowSpan: 2 },                    { name: "G", field: "totalG", width: "60px" },                    { name: "AB", field: "totalAB", width: "60px" },                    { name: "R", field: "totalR", width: "60px" },                    { name: "RBI", field: "totalRBI", width: "60px" },                    { name: "BB", field: "totalBB", width: "60px" },                    { name: "K", field: "totalK", width: "60px" }                ],[                    { name: "Games as Batter", field: "totalGAB", colSpan: 2 },                    { name: "H", field: "totalH" },                    { name: "2B", field: "total2B" },                    { name: "3B", field: "total3B" },                    { name: "HR", field: "totalHR" }                ]            ]        }    ]}, "grid");

Page 48: AMD in Dojo and beyond

Populating your Grid using dojo/dataViewsThe DataGrid is the central component of many applications due to its effective and usable presentation of tabular data. In this tutorial we will look at how to populate a grid and manipulate data in a grid. There are two ways to access the data in the store; the first is letting the DataGrid query the store for you. To do this, we

can pass three parameters to the DataGrid constructor: store: The data store. query: The query to pass to the store. The syntax will depend on the store being used. queryOptions: Options to pass to the store during querying. The options will depend on the store being used, and is not

required. Since we want every record, we'll pass { id: "*" }: require([     "dojox/grid/DataGrid",     "dojo/store/Memory",     "dojo/data/ObjectStore",     "dojo/_base/xhr",     "dojo/domReady!" ], function(DataGrid, Memory, ObjectStore, xhr){     var grid,  dataStore;     xhr.get({         url: "hof-batting.json",         handleAs: "json"     }).then(function(data){         dataStore =  new ObjectStore({ objectStore:new Memory({ data: data.items }) });           grid = new DataGrid({             store: dataStore,             query: { id: "*" },             queryOptions: {},             structure: [                 { name: "First Name", field: "first", width: "25%" },                 { name: "Last Name", field: "last", width: "25%" },                 { name: "G", field: "totalG", width: "10%" },                 { name: "AB", field: "totalAB", width: "10%" },                 { name: "R", field: "totalR", width: "10%" },                 { name: "H", field: "totalH", width: "10%" },                 { name: "RBI", field: "totalRBI", width: "10%" }             ]         }, "grid");         grid.startup();     }); });

Page 49: AMD in Dojo and beyond

Populating your Grid using dojo/dataViewsrequire([    "dojox/grid/DataGrid",    "dojo/store/Memory",    "dojo/data/ObjectStore",    "dojo/_base/xhr",    "dojo/domReady!"], function(DataGrid, Memory, ObjectStore, xhr){    var grid,  dataStore;    xhr.get({        url: "hof-batting.json",        handleAs: "json"    }).then(function(data){        dataStore =  new ObjectStore({ objectStore:new Memory({ data: data.items }) });        grid = new DataGrid({            store: dataStore,            query: { id: "*" },            queryOptions: {},            structure: [                { name: "First Name", field: "first", width: "25%" },                { name: "Last Name", field: "last", width: "25%" },                { name: "G", field: "totalG", width: "10%" },                { name: "AB", field: "totalAB", width: "10%" },                { name: "R", field: "totalR", width: "10%" },                { name: "H", field: "totalH", width: "10%" },                { name: "RBI", field: "totalRBI", width: "10%" }            ]        }, "grid");        grid.startup();    });});

Page 50: AMD in Dojo and beyond

Populating your Grid using dojo/dataViews Formatting Data

{    name: "G", field: "totalG", width: "10%",    formatter: function(games){        return games + " <em>games</em>";    }}, DataGrid as a View One very important point should be made before concluding this tutorial: the DataGrid is simply

aview of a dojo/data store. This means the DataGrid will react to changes in the store (row addition or deletion, and record field

updates) if the store supports the notification API of dojo/data, and it will sort the data according to the rules of the store you're using. However, it is not designed to do sorting apart from the store.

This means that if formatting your data will change the sort order, theDataGrid won't notice the formatted changes.