0

I wrote a class, DataGridPane, extended from a ContentPane which holds a data grid. I have the following problems:

  • In dojo's request.post.then function, the this.xxx property variables are not recognized and show as undefined. Why is this happening?
  • The table doesn't display the data until I drag a split line into the page.
define([
    'dojo/_base/declare',
    'dijit/layout/ContentPane',
    'dojo/dom-construct',
    'dojo/_base/lang',
    'dojo/store/Memory',
    'gridx/Grid',
    'gridx/core/model/cache/Sync',
    'dojo/request',
    'dijit/Tooltip', 
    'dojo/domReady!'
], function (
        declare, 
        ContentPane,
        DomConstruct, lang, Store, Grid, Cache, request, Tooltip) {

    DataGridPane = declare('DataGridPane', ContentPane, {
      id:                   "id",
      title:                undefined,
      url:                  undefined,
      requestType:          "json",
      gridContainer:        undefined,
      layout:               undefined,

      constructor:
        function(params) {
           //......
        },

      start: function() {           
           this.gridContainer = DomConstruct.create("div",{
              id:      "gridDiv"
           }, this.domNode);            
           this.createGrid();
      },

      createGrid:
            function() {
                //Q1:I have to save this.layout to another variable, as the following 
                //code in request.post.then didn't see all this.xxx variables
                var layout = this.layout;
                request.post( this.url, {      //Q1:this.url is OK
                      handleAs: this.urlType    //Q1:this.urlType is OK
                    }
                ).then(
                    // Q1:console.log print 3 'undefined'
                    console.log( this.url + this.urlType + this.layout); 
                    function(response){
                      var datalist = [];
                      var length = 0;

                      dojo.forEach(response.items, function(thisText, i){
                        datalist.push(lang.mixin({ id: i+1 }, thisText));  
                        length++;
                      });
                      var store = new Store({
                        data: datalist
                      });       

                      var grid = new Grid({
                        cacheClass: Cache,
                        store: store,
                        structure: layout
                      }, 'gridDiv');    

                      grid.startup();   
                   }, function(error){
                      console.log("An error occurred: " + error);
                   }
               );
            }
            .......
     });

     //Return the DataGridPane object.
     return DataGridPane;
});

Question 2 is about the response. I made the response the format below:

{
  "items":[...],
  "status":[...],
  "description":[...]
}

response.items hold the list to be show in the table cells; response.status and response.description carry 2 other lists I will use in tool tip. I include these 3 lists in one response instead of sending 3 separate requests to enhance efficiency. However, the table doesn't show anything when the page is loaded. The items in response.items only become visible once I have dragged the split line.

As an experiment, I used a simpler format of the response as follows:

 {
   "items":[...]    
 }

When items is the only element in the response, the items in response.items are displayed when the page is opened, but I'll fail to retrieve enough data for one request. Isn't the dojo request designed to parse the complicated response?

I have tried a call to this.resize() after grid.startup() but it appears to have no effect.

Ryan Ransford
  • 3,224
  • 28
  • 35
anaconda_wly
  • 159
  • 1
  • 2
  • 12
  • The code you've pasted has syntax errors. Double check and edit your answer. (The line with `console.log( this.url ... ` seems misplaced.) Also try to fix the indentation, it makes it easier for others to understand the program (keep in mind that stackoverflow doesn't handle characters). – Frode Jan 14 '14 at 13:16
  • Hi, I re-edited the indention. I removed the comma after createGrid:function{} as in my original code, this is not the last method. But here, it's the last one and the comma should be removed. Sorry I posted the thread in such a haste, I'm eager to know the answer and the best way for me to do. – anaconda_wly Jan 14 '14 at 14:19
  • this.url and other class properties are initialized in the constructor. this.url points to a Perl script printing the Json response. – anaconda_wly Jan 14 '14 at 14:23
  • There's still syntax errors. You seem to have inserted a `console.log` statement in the parameter list for `.then()`. The class property problem (Q1) is a very common Javascript mistake, I advice you to read something like this: http://stackoverflow.com/questions/3127429/ and then http://dojotoolkit.org/reference-guide/1.9/dojo/_base/lang.html#hitch . – Frode Jan 14 '14 at 14:42

1 Answers1

0

Comments get a bit cramped, so I'll expand a bit on the problems mentioned.

Problem 0: Syntax errors (added by me)

There are still syntax errors. You seem to have inserted a console.log statement in the parameter list for .then(). Remove that, so you'll have something like this:

).then(
    // Q1:console.log print 3 'undefined'
    // ------------> You can't have a console.log statement here,
    // ------------> this is the parameter list for then()!
    // console.log( this.url + this.urlType + this.layout); 
    function(response){
       ....
    }, 
    function(error){
       ....            
    });

Problem 2: Class properties not working

This is a very common Javascript mistake, I advice you to take a look at these:

Essentially, one way to solve it is by making local variables, e.g. var layout = this.layout; like you've done (you'll often see people doing var self = this; also). This is because function scope and the this keyword work a little differently from what you're used to (see the aforementioned links).

Alternatively, you can use the hitch() function in dojo/_base/lang to "bind" the function to the this object. That would look something like the following:

define([
    "dojo/_base/lang", // <--------- remember to add this
    /* your other dependencies here... */
], function (
    lang, // <!--------- this too!
    /* your other dependencies here as well, of course.. */
) {
// your other code as before ......

    request.post( this.url, {
            handleAs: this.urlType 
        }).then(
            lang.hitch(this, function(response) {
                // <--------- Now using this.layout etc works here
            }),
            function(error) { /* .... */ }
        );

Problem 3: Grid not showing until you resize the pane

This usually occurrs when the Grid tries to render itself in a DOM node that is detached from the DOM (or the node has display: none or similar). You can try to fix this by calling grid._resize() after you've inserted it in the DOM.

As a quick test, you can do something silly like (do not leave this in there though, it's just for determining the root cause):

setTimeout(function() { grid._resize(); }, 2000);

Edit: Ok, I see you've tried something similar, so this may not be the issue.

Community
  • 1
  • 1
Frode
  • 5,600
  • 1
  • 25
  • 25
  • Thanks for you detailed reply which is very useful. However `setTimeout` seems didn't resolve the problem 3. For 1, console.log is inserted in the wrong place when editing this post. I just compared with my own code. In my code it is in the function scope, not the parameter list. For 2, it's good to know the detail, thanks a lot. – anaconda_wly Jan 14 '14 at 16:44