Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
397 views
in Technique[技术] by (71.8m points)

extjs - Extjs4: How to share data between multiple stores or models?

I'm new to Ext and I'm struggling to figure out Models Stores and Proxies.

The server returns one large JSON object. For example.

{ 
    "responseHeader":{ 
        "status":0, 
        "QTime":12, 
        "params":{ 
            "facet":"true", 
            "facet.limit":"40" 
        }
    },
    "response":{
        "numFound":3806,
        "start":0,
        "docs":[ 
            { 
                //Lots of fields
                "id":"1234",
                ...
                //Some array properties
                "testfield":[ 
                    "",
                    ""
                ],
                ...
            }
        ]
    },
    "facet_counts":{
        "facet_queries":{
            "email":3806
        },
        "facet_fields":{
           "emailaddress":{ 
            },
            "subject":{
                "candles":136,
                "filter":130 
            },
            "fromemail":{ 
            },
           //...
        },
        "facet_dates":{ },
        "facet_ranges":{}
    },
    "highlighting":{
        "some doc id":{
            "emailtext":[ " Tel.: blah blah <em>blah</em>" ],
            "combined":[ "<em>Email</em> To: blah blah blah" ]
        }
    }
}

I don't want to load this data more than once, I want to grab data from this object, for example the docs object, and put it into a grid. Then pull out another part to put into a selectbox.

How do I load this data once, yet create models and stores to give to grids and selectboxes, from it?

From what I read the proxy holds the servers response? So I tried creating a proxy out side of a store. Thinking I could use the same proxy with more than one store.

var myProxy1 = Ext.create('Ext.data.proxy.Proxy', {
    type: 'ajax',
    url : '../test',
    reader: {
        type: 'json',
        root: 'responseHeader'
    }
});

But when I pass myProxy1 to a store

Ext.define('Test', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'status', type: 'int'},
        {name: 'QTime',  type: 'int'},
        {name: 'param',  type: 'auto'}
    ]
});

var myStore = Ext.create('Ext.data.Store', {
    model: 'Test',
    proxy: myProxy1,
    autoLoad: true,
    listeners:{
        load: function( ths, records, successful, operation, eOpts ){
            debugger;
        }
    }
});

It doesn't work. The load event is never fired. No data is loaded. I can see that the proxy made the request, I see the response from the server, but it doesn't load.

If I put the proxy inline it loads.

var myStore = Ext.create('Ext.data.Store', {
    model: 'Test',
    proxy:{
       type: 'ajax',
       url : '../test',
       reader: {
         type: 'json',
         root: 'responseHeader'
       }
    },
    autoLoad: true,
    listeners:{
        load:function( ths, records, successful, operation, eOpts ){
         debugger;
        }
    }
});

I was thinking I could have one proxy, attach it to multiple stores, and just change the reader on it before I load the store.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are pretty much there, and although I'm pretty sure you are understanding it all, for the benefit of others allow me to give an extended answer and a slightly modified solution to your problem.

Definitions:

  • The Model - primarily defines the fields a record has.
  • A Store - holds a collection of records.
  • A Proxy - facilitates server communication through a chosen method (Ajax, Direct, etc.) and maps CRUD (Create/Read/Update/Destroy) operations when such result from a change in the associated store or model.
  • A Reader - Tells a proxy how to interpret the data the server returns.
  • A Grid or Combobox - can display store records.

You scenario is not an uncommon one - while by default ExtJS loads each store separately, it is likely an application would prefer various stores to be loaded at once through a single read call; for example, when rendering one store-dependent component is dependent on another store.

Your code is not far off from achieving this, but here is how I do it. In effect, when a 'master' (Tasks) store loads, the server response also carries the data of a 'slave' (Tags) store, which is then manually loaded to that 'slave' store.

The 'slave' store (notice autoload: false and no read operation):

Ext.define('DL.store.Tags', {
    extend: 'Ext.data.Store',    
    model: 'DL.model.Tag',

    // Notice the tags are actually returned when the tasks are loaded and loaded into this store by the TasksStore.
    autoLoad: false, 
    autoSync: true,

    proxy: {
        type: 'direct',

        api: {
            create:  Tags.Create,
            update:  Tags.Update,
            destroy: Tags.Destroy,
        },

        reader: {
            type: 'json',
            root: 'tags'
        }        
    },    

});

Then the 'master' store:

Ext.define('DL.store.Tasks', {
    extend: 'Ext.data.TreeStore',    
    model: 'DL.model.Task',

    autoLoad: true,   
    autoSync: true,

    root: {
        text: 'Root',
        id: null,
        expanded: true
    },

    proxy: {
        type: 'direct',

        api: {
            create:  Tasks.Create,
            read:    Tasks.Read,
            update:  Tasks.Update,
            destroy: Tasks.Destroy,
        },

    },

    onProxyLoad: function( aOperation )
    {
        // A read request for tasks will also return the user tags.
        // So feed these tags into their store.
        var iResult = aOperation.response.result,
            iTagsStore = Ext.StoreManager.lookup( 'Tags' );

        if ( Ext.isDefined( iResult.tags ) )
            iTagsStore.loadRawData( iResult );

        // We need this line for "Tasks" store to load its own data
        this.callParent(arguments);       
    }
});

Basically all it does is it takes part of the server response and loads it manually to the 'slave' store.

The PHP server side code (for tasks read operation) involves:

return array(
    'success'  => true,
    'children' => $iNodes,
    'tags' => $iTags            
);

Where children is the reader's root of the 'master' store, and tags is additional data that is then loaded into the 'slave' store.

I hope you can work how how to apply these concepts to your code.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...