Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha User
    Join Date
    Mar 2010
    Posts
    14
    Vote Rating
    0
    hermann.rangamana is on a distinguished road

      0  

    Default Major bug in ListStore.java : update() has no effect at all !

    Major bug in ListStore.java : update() has no effect at all !


    Hi there,

    I have a simple grid, with some editable columns. Autocommit is false. When i edit the column, i call a rpc which validate the data and then respond with a full object (that is, modifying column1 may also change column2) so i need more than just commiting the change : i need to update the whole line.

    But even after calling grid.getStore().update(model), the grid desperately does not show my changes. Here is why (after digging into the source code) :
    • The gridview uses the record in the store to render the a cell : that is, if there is a record on the row, GridView uses the record to get the value to render, otherwise it uses directly the model. Here is an excerpt from GridView.java lines 1531 - 1535
    Code:
        if (record != null) {
          val = record.getValue(valueProvider);
        } else {
          val = valueProvider.getValue(m);
        }
    • BUT, once set, the model of a record never changes! So if i have an instance object model M with key "key1" in my store, and then i create another instance M' with the same key, getRecord(M') will always return the original model. That's why my changes are never visible.
    My suggestions to fix this :
    • It's a bad idea to use the model as key of the map "records" in the class Store.java, since it requires model object to properly implement equals/hashcode. Why don't simply use the key provided by the ModelKeyProvider as key of this map ? This will solve a lot of trouble !
    • The method getRecord(M) of Store.java should update the model field of the record if a record already exists, thus ensuring that the returned record contains the actual model, not an older version of the model.

  2. #2
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,717
    Vote Rating
    88
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      0  

    Default


    Thanks for your feedback. A question about the use case before we get into possible fixes and changes:

    What does it mean to update the model, while still maintaining uncommitted changes? I have a few examples here of why this is ambiguous, and important to consider:
    • The Record is intended to track changes made against the original model, to apply them finally before the object is persisted somehow (or to allow a way to undo them). When an update occurs, this can mean several things, but generally that new data is available from some other source, that should override the existing data. It is then up to the application performing the update what should be done with the old changes - if updated from another part of the app, probably they should be dropped. If from the server, it depends on whether or not the user expects to see those updated values over their own changes.
    • The Record object tracks only modified properties - if a property is changed to a new value, then back to the original value, no change is stored. Then, if that model is updated to have another new value in that property, would you expect a new change to be added to the record, returning that field in the model to its original value?
    For some of these cases, it makes sense to track the model key, the changed property, the original value, and the new value, but for most cases this is overkill. At the time when the update is going to be applied, all of this data is available, and this can be written into the application logic. For other cases, it makes sense to always drop (i.e. revert()) changes to the original when an update is about to occur - again, application logic can ensure this happens.

    As for changing this, which cases do we favor? The goal in most of the library is to be general enough to easily solve the basic cases, and extensible/flexible enough to provide enough information for the non-trivial ones. I agree we should perhaps make better use of the String key when managing records, but might that not imply that records are meant for managing any more than the original model that the changes were applied to?

  3. #3
    Sencha User
    Join Date
    Mar 2010
    Posts
    14
    Vote Rating
    0
    hermann.rangamana is on a distinguished road

      0  

    Default


    Hi Colin,

    I'm not sure you understand my issue. Let me explain it in a simple example.

    Consider you write an application that archives stock data (last quote, and change in % comparing to the day before's last). The user may manually changes last quote. But the server is the one responsible for computing the "change" column. My grid would look like this one : http://www.sencha.com/examples-dev/#...lace:basicgrid, the column "last" being editable and autocommit set to false.
    So now, what happens when the user edit the the last column of a stock, say "Apple Inc." ? The sequence can look like the following :

    1. The user edit the column "last" and enter "150"
    2. A change is added on the corresponding record (Store.java)
    3. The client code call the server with something like "updateLast("Apple Inc.", 150)"
    4. The server set the last quote of Apple, AND calculate the change
    5. The server respond by sending a Dto (maybe an instance of Stock) with the correct values of last and change.
    6. Upon receiving this, the client code calls list.getStore().update(newStock)
    7. And on the grid, the user expects to see that the last AND the change columns have changed.

    Just committing the changes on stage 6 on the ListStore is unsufficient : the column "change" has also changed!

    This simple usecase won't work unless i correctly implement equals/hashCode on my class Stock, because Stock objects (my model) are used as key of a map (cf Store fields "records" and "modifiedRecords").

    I believe that just using the key provided by the ModelKeyProvider of the store as key of those maps (fields "records" and "modifiedRecords") is far better and will easily solve this problem (i took me a couple of hour to override this behaviour whith zero api changes by creating a subclass of ListStore)

    thanks

    HR

Thread Participants: 1