Step 5 – Create the Custom Model

The default dijit Tree relies on a dojo ItemFileReadStore to load our Json file however, in order to satisfy several of our requirements we need to be able to maintain the status of our checkboxes at the data store level. To do that we need a ItemFileWriteStore instead. Lets make the changes to our index.html to reflect our requirement:

 10   <script type="text/javascript">
 11       dojo.registerModulePath("tmpdir","/js/tmpdir");
 12       dojo.require("dojo.data.ItemFileWriteStore");
 13       dojo.require("tmpdir.CheckBoxTree");
 14 
 15     function myTree( domLocation ) {
 16       var store = new dojo.data.ItemFileWriteStore( {
 17               url: "/js/datastore/countries.json"
 18               });
 19       var model = new tmpdir.CheckBoxStoreModel( {
 20               store: store,
 21               query: {type: 'continent'},
 22               rootId: 'root',
 23               rootLabel: 'Continents',
 24               });

On line 12 we are now including the ItemFileWriteStore and on line 16 we create the write store instead of a read store. In reality nothing will happen to the current behavior of our widget because the ItemFileWriteStore just extends the ItemFileReadStore.

Next we are going to create our model and put all the basic hooks and callbacks in place. Open your CheckBoxTree.js file and make the following enhancements:

  1 dojo.provide("tmpdir.CheckBoxTree");
  2 dojo.provide("tmpdir.CheckBoxStoreModel");
  3 dojo.require("dijit.Tree");
  4 
  5 dojo.declare( "tmpdir.CheckBoxStoreModel", dijit.tree.ForestStoreModel,
  6 {
  7   updateCheckbox: function(storeItem, newState ) {
  8   },
  9 
 10   onCheckboxChange: function( storeItem ) {
 11   }
 12 });
 13 
 14 dojo.declare( "tmpdir._CheckBoxTreeNode", dijit._TreeNode,
 15 {
 16   _checkbox: null,
 17 
 18   _createCheckbox: function() {
 19       this._checkbox = dojo.doc.createElement('input');
 20       this._checkbox.type    = 'checkbox';
 21       this._checkbox.checked = currState;
 22       dojo.place(this._checkbox, this.expandoNode, 'after');
 23     }
 24   },
 25 
 26   postCreate: function() {
 27     this._createCheckbox();
 28     this.inherited( arguments );
 29   }
 30 });
 31 
 32 dojo.declare( "tmpdir.CheckBoxTree", dijit.Tree,
 33 {
 34   onNodeChecked: function(/*dojo.data.Item*/ storeItem, /*treeNode*/ nodeWidget) {
 35   },

On line 2 we tell dojo that our CheckBoxTree.js file now also includes our new model called .CheckBoxStoreModel. On line 5 we start the declaration of our model which currently has two methods: updateCheckbox and onCheckboxChange. The last one should sound familiar to you.

The method updateCheckbox will be called by the tree whenever a checkbox is clicked. Basically this is the way the tree will let the model know things have changed on the tree side. The onCheckboxChange method is a callback which will trigger an event if something on the store side has changed. So next we add the call to updateCheckbox to our tree, where you would ask? Well as part of the _onClick method of the tree.

 40   _onClick: function(/*Event*/ e) {
 41     var domElement = e.target;
 42     if(domElement.nodeName != 'INPUT') {
 43       return this.inherited( arguments );
 44     }
 45     var nodeWidget = dijit.getEnclosingWidget(domElement);
 46     if(!nodeWidget || !nodeWidget.isTreeNode){
 47       return;
 48     }
 49     nodeWidget._checkbox.checked ^ true;
 50     this.model.updateCheckbox( nodeWidget.item, nodeWidget._checkbox.checked );
 51     if(nodeWidget._checkbox.checked) {
 52       this.onNodeChecked( nodeWidget.item, nodeWidget);
 53     } else {
 54       this.onNodeUnchecked( nodeWidget.item, nodeWidget);
 55     }
 56   },
 57 
 58   postCreate: function() {
 59     this.connect(this.model, "onCheckboxChange", "_onCheckboxChange");
 60     this.inherited(arguments);
 61   },

On line 50 we call the updateCheckbox method of our model and pass the store item associated with the tree node widget and the new state of our checkbox. I have also uncommented line 58 and thus we will start listening to any onCheckboxChange events triggered by our model. As a final result our event driven CheckboxTree widget has all the plumbing in place.

To recap, any browser click events are caught by the tree _onClick method which will call the updateCheckbox method on our model and if any changes occur on our store/model the model will trigger the onCheckboxChange event which will be caught by the tree which will then update the checkbox on the tree node. Are you still with me? No? Let’s try a picture then:

SequenceDiagram1

Next STEP 6 Adding attributes.

Leave a Reply

Your email address will not be published. Required fields are marked *