7
votes

I want to get an onload event working on my config object.

The following works, except when I create a

config.listeners={..}

(I think that's what I need?) to replace

this.onload({...});

Am I even using the right config? (I generally have no clue about event handling)

Ext.define('data.SimpleStore', {
extend: 'Ext.data.Store'
,constructor: function (config) {

    config.url=config.url||"afsud"; //If no call, we assume that url has been passed. Pass neither and be shot
    config.id=config.url+'Store';//call should be unique, else its another set of headaches. 
    //console.log(config);
    Ext.define(config.id+'M', { //for a painful reason, you cant have a store without a model
        extend: 'Ext.data.Model',
        fields: []//we figure these out anyways
    });
    config.root=config.root||'data';
    config.type=config.type||'json';
    config.proxy= config.proxy||{ //note if we override our proxy, then server.php might not work as black magic
        type: 'ajax'
        ,url : config.url
        ,reader: {
             type: config.type//seriously if you want to change this, go away
            ,root: config.root//we assume. 
        }
    };
    config.model=config.id+'M';//model should match store anyway. Generic models are out of scope atm
    config.listeners={
        //this.populateFields //Error'd
    };
    this.callParent([config]);
    this.load({//This works, but its after the parent call, so not exactly what i want
        callback: function(records,operation,success){
            var obj=Ext.decode(operation.response.responseText);     
            this.add(obj[config.root]);
            console.log(this.getRange());
            console.log(config);
        }
    });
}
,populateFields:function(){
    console.log('ran'); // never happens
}
});

var s=   Ext.create('data.Store',{url:'test.php'});
s.load();
4
Since this is getting a lot of hits, there was a nice writeup about listeners from one of sencha's guys. mitchellsimoens.com/2011/12/ext-js-4/…Alex

4 Answers

20
votes

In ExtJS events are managed by using two ways:

Firstly, You can add in your config listeners object:

var s = Ext.create('data.SimpleStore',{
  url:'test.php',
  listeners: {
    'load': function(store, records, successful,operation, options) {
      //Here you are handling onload event
    }
  } //Don't forget to close all code blocks
});
s.load();

Secondly, you can use on method:

var s = Ext.create('data.SimpleStore',{url:'test.php'});
s.on('load', function(store, records, successful,operation, options) {
  //Here you are handling onload event
});
s.load();
4
votes

To add to Molecule's first answer, which I use frequently in my enterprise apps, because it is more succinct and easier to read.

It is often easier to use a Bus to pass messages around your app.

myApp.Bus = new Ext.util.Observable();
myApp.Bus.addEvents(
    'myCustomEvent'
);

Then in your application use the following to fire to the bus:

myApp.Bus.fireEvent( 'myCustomEvent', {someData: value} );

And where you want to listen for the event:

... // config
myObj.on('myCustomEvent', function(someData) { doSomething(); }, this);
3
votes

A few thing before introducing my way of coding:

  1. Usually I don't assign id to Ext Objects, as it's a bad practice. We only need ids in very rare cases, and unless there is absolutely no way to access an object without using an id (I can't think of a reason).
  2. You are wrong about "You can't have a store without a model". Using Model is a good practice, but you can always define one Store without a model, and it will help you to create one automatically.
  3. If you have default values, it'll be good to put it in the class properties.
  4. More like for consistencies, we end a line with comma, not start with comma.

So to clean your code up a bit, I came out with this piece of code (demo of this code):

/**
 * First, you might need to describe what is your class about.
 * 
 * So this is the SimpleStore of my App bla bla..
 * 
 * Also take note that "data" is a bit too generic to be a Namespace. Try
 * something else. Namespace always defined in CamelCase.
 */
Ext.define('MyApp.data.SimpleStore', {

    extend: 'Ext.data.Store',

    /**
     * We often define those 'default' variables in this section.
     * One thing is to make it more 'ext' like.
     */

    /**
     * @cfg {string} url
     * Description...
     */
    url: 'afsud',

    /**
     * @cfg {string} root
     * Description..
     */
    root: 'data',

    /**
     * @cfg {string} type
     * Description...
     */
    type: 'json',

    /**
     * @cfg {boolean} autoLoad
     * We make autoload = true here, so we can
     * always have the store loaded on initialization
     */
    autoLoad: true,

    /**
     * Creates the Store
     * @param {Object} cfg
     */
    constructor: function(cfg) {

        //Since ExtJS4, we often use variable 'me' to refer 'this'.

        //Thou in this case we didn't use much of 'me', but it's much
        //cleaner than 'this' yeh?
        var me = this;

        //Simply override everything here, no special logic required.
        Ext.apply(me, cfg || {});

        me.proxy = {
            type: 'ajax',
            url: me.url,
            reader: {
                type: me.type,
                root: me.root
            }
        };

        me.callParent(arguments);

        //Then we add our events
        /**
         * In ExtJS, we always add events after a constructor has been called,
         * or after initComponent has been called. We then add the events by using
         * this method.
         * 
         * The .on method is defined in Ext.util.Observable. Observable is a class
         * inherited by almost everything in ExtJS. It's also a nice class
         * to base from if you write your own stuff which supports Event Management.
         * 
         * .on is the shorthand for addListener, and .un is its opposite.
         * 
         * We add an handler to the load event, with the handler defined as me.onLoad,
         * and scoped to this object.
         */
        me.on('load', me.onStoreLoad, me);

        me.on('beforeload', me.onBeforeLoad, me);
    },

    /**
     * This is optinal, purely just to show you the code is running
     */
    onBeforeLoad: function(st) {
        alert('Store is trying to retrieve data from '+st.url);
    },

    /**
     * Handling the load event..
     * 
     * @param {Ext.data.Store} st The store
     * @param {Array} records An array of records
     */
    onStoreLoad: function(st, records) {
        if (!records) alert('And it seems like we cannot reach '+st.url);
    }
});

//Then later in your code, you call your store.
//Remember that we set autoLoad:true, so you don't need to call
//s.load() again.
var s = Ext.create('MyApp.data.SimpleStore', {
    url: 'test.php'
});

Event handling in ExtJS is very well defined and structured. You can always visit this page to know more about Event Handling.

If you are unsure how to code ExtJS, you can always look at their source code and learn from experts.

Extra Note

The this.load(.. you mentioned in your code is in fact a method defined in Ext.data.Store, which asks the Store to execute the load action, and on success, the Store will load callback that you have specified. I think this is not the load event that you have mentioned.

Good luck and cheers!

0
votes

Be sure to attach events when components have been rendered. My solution overides the initEvents() function of components

Ext.define('MyApp.grid.MyGrid', {
  extend: 'Ext.grid.Panel',
  initEvents: function() {
    // attach events here
    this.callParent(arguments)
  }
});