6 Replies Latest reply on Jul 7, 2010 11:44 AM by jsd99

    Accessing AdvancedDataGrid row/cell directly

    =VA=FyreHeart Level 2

      I run into this problem  repeatedly, and every time I have to find a wonky workaround.

       

      In essence, I  need get direct access to a cell in an ADG - properties, data, row  index, etc.

       

      In this case, I'm working on an accounting application:

      I have an ADG with some deeply  nested heirarchical data. Each level gives the user more detail. So,  for each "row" in the dataProvider, the ADG has at least three summary  rows corresponding to SuperCategory, Category, and SubCategory.

       

      When a user  double-clicks on a number, it's supposed to pop up with the specific  budget line items that make up that total. Problem is, when I create a  cursor to traverse the ADG, the rowIndex returned by the ListEvent takes  summary rows into account, but the dataProvider doesn't. Therefore, I  don't get the data the user clicked on, and if they click way down the  list it runs off the end and returns an error.

       

      Example:

      dataProvider:

      Row1:  SuperCategory Category SubCategory Account1 $Amount1

      Row2:   SuperCategory Category SubCategory Account2 $Amount2

      etc...

       

      ADG:

      SuperCategory

            Category

                SubCategory

                     Account1 |  $Amount1 <- USER CLICKS HERE

       

      The ADG ListEvent.rowIndex = 3, but the row  in the dataProvder = 0. Just subtracting four only works for the first  group, b/c apparently the row numbers are cumulative, not heirarchical.

       

      Using the  ADG's indicesToIndex method doesn't work, either. Apparently, it counts cells and runs off the end if you click  too far down in the grid.

       

      So... how do I get the ADG to return Account1  when user clicks on $Amount1?

       

      Thanks.

        • 1. Re: Accessing AdvancedDataGrid row/cell directly
          =VA=FyreHeart Level 2

          I found a solution, that IMHO falls into the "wonky workaround" category: It turns out the ListEvent object does pass the row's

          data, but it was buried several layers deep in the itemRenderer. (Why would raw data be in an itemRenderer?)

           

          I still don't understand why a data structure representing the datagrid doesn't exist, though. E.g.

          Row1=array(column1=>value1, column2=>value2),

          Row2=array(column1=>value3, column2=>value4)

          ...so we could access the cell by dataGrid[rownum][colnum].property

           

          Oh, well.

          • 2. Re: Accessing AdvancedDataGrid row/cell directly
            jsd99 Level 3

            You're not supposed to know about what's where in the datagrid.  Think model-view-controller separation.  What if the datagrid could magically change the way it looks on the fly for some reason?  The idea of "row 3 column 7" would be meaningless.  Also, cells and rows in the datagrid control are re-used for efficiencies sake.  (Imagine you have 1000 rows but are only displaying 8 at a time - you don't want the datagrid having unused cells for the other 992 rows wasting memory).

             

            Store a pointer to the data that's relevant in the itemRenderer class, then when it is clicked you can send an event with that data back.

            1 person found this helpful
            • 3. Re: Accessing AdvancedDataGrid row/cell directly
              =VA=FyreHeart Level 2

              I understand your point about the DataGrid changing appearance and reusing renderers, which is why I said "a data structure representing the datagrid." I.e. not the datagrid itself, but rather a multi-dimensional array representing the datapoints displayed in the grid. (The Model piece of the grid, not the View.) That data structure effectively already exists in memory, otherwise sorting functions wouldn't work. It's just absurdly hard to access.

               

              What if I need access to summary data that's calculated on the fly? That data isn't passed in the ListEvent object, so I have to manually recalculate it, which wastes processor and memory resources when it's already been done.

               

              However, this does make me rethink my opinion of accessing display properties. Reusing renderers is ultimately more efficient, which means styling by a callback function is the best way to do it, rather than styling each individual cell at creation time. So, I retract my statements as it relates to the View layer (but not the Model. )

              • 4. Re: Accessing AdvancedDataGrid row/cell directly
                jsd99 Level 3

                =VA=FyreHeart wrote:

                 

                I understand your point about the DataGrid changing appearance and reusing renderers, which is why I said "a data structure representing the datagrid." I.e. not the datagrid itself, but rather a multi-dimensional array representing the datapoints displayed in the grid. (The Model piece of the grid, not the View.) That data structure effectively already exists in memory, otherwise sorting functions wouldn't work. It's just absurdly hard to access.

                 

                It shouldn't be hard at all.  You already have the model.  You can just give the itemrenderer a hint to know which piece of the model it's representing.  (If my model is an arraycollection, I just store a pointer to the particular array entry in the itemRenderer).

                 

                What if I need access to summary data that's calculated on the fly? That data isn't passed in the ListEvent object, so I have to manually recalculate it, which wastes processor and memory resources when it's already been done.

                 

                If you will need to access it again, calculate it and store it in your data model.

                 

                However, this does make me rethink my opinion of accessing display properties. Reusing renderers is ultimately more efficient, which means styling by a callback function is the best way to do it, rather than styling each individual cell at creation time. So, I retract my statements as it relates to the View layer (but not the Model. )

                 

                It takes a little thought ahead of time but Flex is essentially an MVC framework so making your program conform to those concepts is going to be much more pleasant than trying to work around it with hacks and kludges.

                • 5. Re: Accessing AdvancedDataGrid row/cell directly
                  =VA=FyreHeart Level 2
                  It shouldn't be hard at all.  You already have the model.  You can just give the itemrenderer a hint to know which piece of the model it's representing.  (If my model is an arraycollection, I just store a pointer to the particular array entry in the itemRenderer).

                   

                  OK, but this is my point. Why would the itemRenderer (a View-layer component) be storing anything about the raw data (a Model-layer component)? That's counter-intuitive, breaks the MVC model, and IMHO, is harder to access than dataGrid.data[row][column].

                  If you will need to access it again, calculate it and store it in your data model.

                   

                  Exactly. Which is inefficient. I deal with datasets of tens or hundreds of thousands of rows, so having to calculate things twice can take a significant amount of time and delays the application response for my end users.

                   

                  Honestly, I can't complain too much, since Flex has made a number of development tasks much easier on me. But some of the roadblocks I run into, especially related to advanced functionality in the DataGrids, don't seem very logical.

                  • 6. Re: Accessing AdvancedDataGrid row/cell directly
                    jsd99 Level 3

                    =VA=FyreHeart wrote:

                     

                    It shouldn't be hard at all.  You already have the model.  You can just give the itemrenderer a hint to know which piece of the model it's representing.  (If my model is an arraycollection, I just store a pointer to the particular array entry in the itemRenderer).

                     

                    OK, but this is my point. Why would the itemRenderer (a View-layer component) be storing anything about the raw data (a Model-layer component)? That's counter-intuitive, breaks the MVC model, and IMHO, is harder to access than dataGrid.data[row][column].

                    The itemRenderer has to have *some* idea of the model, otherwise what's it going to display?  It shouldn't be *changing* the model though... I don't see storing a pointer to a piece of the model as violating the MVC paradigm.  ItemRenderer is sort of a hybrid view-controller anyway.  A true view would be like a button, which doesn't do anything except display a control and dispatch events out.

                     

                    dataGrid.data[row][column] wouldn't work unless it was storing all the rows & columns, which, as we discussed, it doesn't do, in the name of efficiency.