ExtJS 4 - Update/Refresh single record
Asked Answered
H

4

9

I have a problem that's bugging me.

I have a grid and when i dblclick on a item I want to open a window to edit that item. Pretty standard stuff. The problem is, i want to be sure the record is up to date, because other people using the program may have changed it or even deleted it.

I could reload the store, but i only want one specific record to be checked... So i figured i would just go get the data, build another record and replace the existing one in the store but i really want to know the best way to do this

Bear in mind RESTful proxy is not an option for me, even though i don't know if the update operation works in this case ( server -> client).

EDIT: this may help somebody: all i did was copy the data and raw objects from the new record to the old one and then "commit" the changes. worked for me.

Thank you.

Happily answered 3/6, 2011 at 1:47 Comment(0)
M
4

The best way to do something like this would be to reload the record in the event which opens the window. So where you would for example load the record from the grid store into a form within the window, you can use your model to load from the id.

Item.load(id, { success: function(r) { form.loadRecord(r); } });

Once saved, you should probably also call refresh on the grid view, which will redraw the changes from the save event. You can also use refreshNode (see grid view documentation) on the exact record in the store if you're concerned about performance.

Of course you do not have to use the restful proxy with this, you can use any proxy as long as it will load the single record.

Microscopy answered 3/6, 2011 at 13:8 Comment(6)
The load function (on the Model) builds another record (and that's why a posted this question :D ) when i dblclick the item i got the record already, and i only want to reload it, not build another, or if so, how to replace the old one cleanly. Thank you Simon.Happily
If you are wanting to check the freshness against the server, then you will have to load a new version. If you want to stick solely to the grid's backing store, instead of using the standalone model, you will have to remove the record from the store, and then load({add: true}) on the grid store using a url that just grabs the relevant record.Microscopy
so, there's no way to reload it... ok, thank you, i'll accept your answer because it actually helped me on the "refresh grid" issue. i was afraid that it would flick or something when i deleted and then added (or vice-versa) the records in question. thank you.Happily
This solution sucks, because you're creating another object in memory - and the item in the store will be out of sync if you update the newly loaded item.Ulster
Hi Simon, in fact I am curious to see the link you provided above but it is not working. can you post new link please?Dennet
Hi, sorry about that, I've fixed the link now, should go to the latest docs.Microscopy
B
6

ExtJS 4.1

I had a similar problem and as an experiment tried

sStore.load({ id: mskey, addRecords: true });

where mskey is a uuid of a currently loaded record.

I did not remove the existing record first (as an experiment) and it updated the existing record that had the same id with the new data from the server (via the model --> REST proxy). Perfect!

I know you said you are not using a REST proxy, but this might help others who found this post searching for search terms like your topic name (which is how I got here!)

So, it looks like 'addRecords' means add or update.

FYI, Murray

Brigandage answered 18/4, 2013 at 11:17 Comment(1)
Unfortunately, this reset the scrolling position and added the updated records always at the end of my grid. I used a modified version of a script found here instead: vadimpopa.com/…Dingus
M
4

The best way to do something like this would be to reload the record in the event which opens the window. So where you would for example load the record from the grid store into a form within the window, you can use your model to load from the id.

Item.load(id, { success: function(r) { form.loadRecord(r); } });

Once saved, you should probably also call refresh on the grid view, which will redraw the changes from the save event. You can also use refreshNode (see grid view documentation) on the exact record in the store if you're concerned about performance.

Of course you do not have to use the restful proxy with this, you can use any proxy as long as it will load the single record.

Microscopy answered 3/6, 2011 at 13:8 Comment(6)
The load function (on the Model) builds another record (and that's why a posted this question :D ) when i dblclick the item i got the record already, and i only want to reload it, not build another, or if so, how to replace the old one cleanly. Thank you Simon.Happily
If you are wanting to check the freshness against the server, then you will have to load a new version. If you want to stick solely to the grid's backing store, instead of using the standalone model, you will have to remove the record from the store, and then load({add: true}) on the grid store using a url that just grabs the relevant record.Microscopy
so, there's no way to reload it... ok, thank you, i'll accept your answer because it actually helped me on the "refresh grid" issue. i was afraid that it would flick or something when i deleted and then added (or vice-versa) the records in question. thank you.Happily
This solution sucks, because you're creating another object in memory - and the item in the store will be out of sync if you update the newly loaded item.Ulster
Hi Simon, in fact I am curious to see the link you provided above but it is not working. can you post new link please?Dennet
Hi, sorry about that, I've fixed the link now, should go to the latest docs.Microscopy
O
1

With ExtJS 4.1, here is an override :

In CoffeeScript :

# Adds "reload" to models
Ext.define "Ext.ux.data.Model",

    override: "Ext.data.Model",

    # callBack is called with success:boolean
    reload: (callBack) ->
        Ext.getClass(@).load @getId(),
            success : (r, o) =>
                for k, v of r.data
                    @data[k] = v
                @commit()
                callBack(true) if Ext.isFunction(callBack)

            failure: =>
                callBack(false) if Ext.isFunction(callBack)

In JS (did not test) :

Ext.define("Ext.ux.data.Model", {

    override: "Ext.data.Model",

    reload: function(callBack) {

        var me = this;
        return Ext.getClass(this).load(this.getId(), {
            success: function(r, o) {
                var k;
                for (k in r.data) {
                    me.data[k] = r.data[k];
                }
                me.commit();
                if (Ext.isFunction(callBack)) {
                    callBack(true);
                }
            },
            failure: function() {
                if (Ext.isFunction(callBack)) {
                    callBack(false);
                }
            }
        });
    }
});
Occur answered 23/1, 2013 at 10:59 Comment(3)
This is not a good idea to modify private data property. Better use set method instead.Trevatrevah
@AlexeySolonets set would mark the record as "dirty", which is not the case here.Occur
of course we should use suspendEvents, commitand resumeEventsTrevatrevah
K
0

I created an override on the Ext.data.Model to add an additional method that can be used to update the data of an existing record (model instance).

Ext.define('Ext.overrides.data.Model', {
    override: 'Ext.data.Model',

    /**
     * Refresh the data of a record from the server
     */
    reloadData: function(cb) {
         var me = this;

         var id = me.getId();

         Ext.ModelManager.getModel(me.modelName).load(id, {
            callback: function(record, operation, success) {
                if (!success) {
                    Ext.Error.raise('Problem reloading data from server in record');
                }
                if (!record) {
                    Ext.Error.raise('No record from server to reload data from');
                }
                //change the data of the record without triggering anything
                Ext.apply(me.data, record.getData());

                //call a final callback if it was supplied
                if (cb) {
                    cb.apply(me, arguments);
                }
            }
        });

        return me;
     }
});

This is how you can use it. It's actually pretty simple:

myRecord.reloadData(function(record, operation, success) {
    //Done updating the data in myRecord
});

Internally it uses the load method on the associated model to create a new record. That new record is based on the same id as the original record that the reloadData method was called on. In the callback the data of the new record is applied to the data of the original record. No events triggered, which is probably hat you want.

This is Ext 4.2.1. There's probably dozens of scenario's that this solution breaks but we can always refine can't we.

Update: This solution basically implements the same as the one by @Drasill. Oh well... This one was tested though.

Kickback answered 18/2, 2016 at 20:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.