Results 1 to 4 of 4

Thread: Making a grid stateful causes problems getting column model

    Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Ext JS Premium Member
    Join Date
    Aug 2010
    Posts
    66

    Exclamation Making a grid stateful causes problems getting column model

    Hi! I'm a little hesitant stating this is a bug outright because it could definitely be a problem in our own code, though I'm suspecting a bug at this point.

    Let me give some backround...

    I've got a very complex app that is based around the notion of multiple windows. For example, we have the ability to view an account in an account window, and the user can open as many of these as they like. So, as you can imagine, there's some fairly complex logic in place to ensure that everything in each instance of the window is unique, meaning no component ID collisions, unique Store instances backing the unique grid instances in each window, all while using the same underlying code to create the windows. Also, the grids in the windows can be exported to various formats via a submission of JSON built from the grid and its store and sent to the server.

    The actual mechanics and reasoning behind this architecture is pretty much irrelevant to this bug, however, I wanted to give you that background so you understand more what you're about to look at. Here's a sample that demonstrates the problem under 6.0.2, boiled down as far as I could go:

    Code:
    Ext.define("myModel",
      { extend : "Ext.data.Model", fields : [ "field1", "field2" ] }
    );
      
    Ext.onReady(function() {
      
      new Ext.Viewport({
        items : [
        
          { xtype : "button", text : "Open Window", 
            handler : function() {
              
              var createTime = new Date().getTime();
              var myStore = Ext.create("Ext.data.Store", { 
                id : "s" + createTime, model : "myModel", 
                data : [ 
                  new myModel({ field1 : "A-111", field2 : "B-222" })
                ]
              });
              
              new Ext.Window({
                x : 100, y : 50, width : 260, height : 150, layout : "fit",
                id : "w" + createTime,
                items : [ 
                  { xtype : "grid", store : myStore, id : "g" + createTime,
                    title : "myGrid",
                    stateful : true, stateId : "state_myGrid",
                    buttons : [
                      { text : "Export",
                        handler : function() { exportGrid(this.up("grid")); }
                      }
                    ],
                    columns : [
                      { text : "field1", dataIndex : "field1" },
                      { text : "field2", dataIndex : "field2" }
                    ]
                  }
                ]
              }).show();      
              
            }
          }
        ]
      });
    
    });
    
    function exportGrid(inGrid) {
    
      console.log("grid", inGrid.id, inGrid.stateId, inGrid);    
      var store = inGrid.getStore();
      console.log("store (" + store.id + ")", store);    
    
      // Construct array of columns that will be exported in the order they appear
      // in the grid (there is more logic built into the real version of this,
      // skipping hidden columns for example, but for our purposes here this is all 
      // that matters).
      var colsOrder = "";
      var cols = [ ];
      var columnModel = inGrid.columns;
      console.log("columnModel (" + columnModel.length + ")", columnModel);        
      for (i = 0; i < columnModel.length; i++) {
        var col = {
          header : columnModel[i].text,
          dataField : columnModel[i].dataIndex
        };
        console.log("col", col);        
        cols.push(col);
        if (colsOrder !== "") {
          colsOrder += "~~";
        }
        colsOrder += columnModel[i].text;
      }
    
      // This object will contain everything the server needs to generate the
      // output file.
      var outputObject = {
        worksheetName : inGrid.initialConfig.title, 
        columnsOrder : colsOrder, content : [ ]
      };
    
      // For each record in the store, grab the value of each column in the grid
      // and the header in the grid and build a simple data object from it.
      store.each(function(rec) {
        console.log("rec", rec);
        var rowObject = { };
        for (var i = 0; i < columnModel.length; i++) {
          var fieldValue = rec.get(cols[i].dataField);
          rowObject[cols[i].header] = fieldValue;
        }
        outputObject.content.push(rowObject);
      });
    
      console.log(Ext.JSON.encode(outputObject));
    
    };
    So, in a nutshell: fire that up, click the button to open a window and then click the Export button and in the console you will, at the end, see some JSON that should be pretty obvious in meaning. Now, close the window and then open a new one and click Export again. This time you'll find that the JSON is basically empty. D'oh!

    The problem boils down to the line:

    Code:
    stateful : true, stateId : "state_myGrid",
    If you comment that out you'll find that export always works as expected (and that remains true even if you open multiple windows simultaneously).

    As you can see, the stateId is NOT unique, while everything else is unique (window/grid ID's, store instance). That's by design because we need to ensure that if I move or resize columns in a window, its state gets saved, and then if I open another window it uses that saved state, even though the grids themselves in each window have unique IDs, hence applying the same stateId to each seems to make sense.

    But, that appears to be the crux of the problem: if I make the stateId something like "state_myGrid"+createTime so that it's unique then the problem goes away. So, it seems like there's something going on with state that I'm not understanding, but to me that SEEMS like a bug because I can't see any reason why I shouldn't be able to do this.

    Put it another way: given two totally separate grids both with the same stateId, shouldn't the saved state properly apply to both? And, I'm not sure why any of this would have any impact on my ability to get at the column model as is needed in the export function.

    Any insight would be GREATLY appreciated because this has become a pretty significant issue for my project.

    Thanks!
    Frank

  2. #2
    Sencha Premium User evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    19,250

    Default

    "columns" is not a property of the grid, it's an initial configuration. To grab all the leaves, use:

    Code:
    grid.getColumnManager().getColumns();
    Twitter - @evantrimboli
    Former Sencha framework engineer, available for consulting.
    As of 2017-09-22 I am not employed by Sencha, all subsequent posts are my own and do not represent Sencha in any way.

  3. #3
    Ext JS Premium Member
    Join Date
    Aug 2010
    Posts
    66

    Default

    Thank you Evan, that's not quite what I was looking for but it did actually put me onto the right answer: inGrid.initialConfig.columns does what I want (I really did just want the column configurations as specified in the initial config... and I really should have realized how to get that myself, d'oh!). Although, I'm still not sure I understand why just adding a stateId all of a sudden makes the code I posted fail to work, but I'm happy to have a solution if not an understanding at this point

    Oh, and I just accidentally tried it under 6.0.1 and it does the same thing so at least we know for sure it's not a 6.0.2-specific thing, which is good.

    Thanks again!

    (and now I'd say this probably IS NOT a bug, though I suppose it still could be given the difference stateId makes, but I'm dubious on that)

  4. #4
    Ext JS Premium Member
    Join Date
    Aug 2010
    Posts
    66

    Default

    Never mind, forget that last post, your answer was the right one Evan I fooled myself into thinking it wasn't because in my simple example here using inGrid.initialConfig.columns does indeed solve the problem. Unfortunately, it failed when I dropped it back into the real code because I forgot that this was a much simplified example and one of the things I removed from it was the fact that the real code skips hidden columns, so it's calling isHidden() on a given column, which obviously isn't going to work if I get the column from initialConfig. D'oh! Your suggestion works perfectly though. I'm not sure at what point the original code stopped working because it definitely did, but a few months back we did a 4.x to 6.x migration so I'd bet there was a change there that did it (though as in my previous response I still don't get why adding stateId does this regardless, but I'm happy now!)

Similar Threads

  1. [FIXED] Stateful grid column sort is not remembered if store binding is used
    By nikolay.bobrovskiy in forum Ext JS 6.x Bugs
    Replies: 8
    Last Post: 27 Oct 2018, 7:16 AM
  2. Replies: 2
    Last Post: 18 May 2016, 1:12 AM
  3. Ext JS 4.2 Stateful Grid Column Ordering Issue
    By cpsarathe in forum Ext: Q&A
    Replies: 2
    Last Post: 14 Jan 2015, 9:59 AM
  4. TreeGrid Hide columns and making it stateful
    By mohan_b in forum Ext 3.x: Help & Discussion
    Replies: 0
    Last Post: 16 May 2011, 8:06 AM
  5. Grid Column Model Problems
    By underdog in forum Ext 2.x: Help & Discussion
    Replies: 2
    Last Post: 13 Apr 2008, 11:41 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •