extjs - Store with autoload true should not load on application launch
Asked Answered
J

3

8

I have a grid linked to a store with autoLoad: true. The problem is that the store gets loaded on application launch, even if the view is created only later when accessed through a menu.

I have referenced the store in Application.js and in the view, but I'm not instatiating explicitly neither the store nor the view.

I don't know how to achieve that the store is loaded only when needed by the view.

  • If I set autoLoad: true, the store gets loaded on application launch.
  • If I set autoLoad: false, the store doesn't get loaded at all.

I know this is pretty basic, but I'm stuck so far.


Here is all the relevant code for reference:
app/store/Owners.js

Ext.define('Mb.store.Owners', {
    extend: 'Ext.data.Store',
    model: 'Mb.model.Owner',
    autoLoad: true,
    proxy: {
        ...
});

Application.js

Ext.define('Mb.Application', {
    name: 'Mb',
    extend: 'Ext.app.Application',
    models: [
        'Owner'
    ],
    stores: [
        'Owners'
    ],
    ...

app/view/Owners.js

Ext.define('Mb.view.winbiz.Owners', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.test-gridPanel',
    store: 'winbiz.Owners',
    columns: [{
    ...

The view is instantiated in the controller:

Ext.define('Mb.controller.Winbiz', {
    extend: 'Ext.app.Controller',
    views: [
        'Owners'
    ],
    init: function(){
        this.control({
            'menu #test': {click: this.onMenuTest},
        })
    },
    onMenuTest: function(){
        this.getController('Main').addToMainTab('test-gridPanel');
    },
Joappa answered 25/10, 2013 at 11:37 Comment(0)
L
8

You can add render handler to view which will call store load method and disable autoLoad.

Example listener:

Ext.define('Mb.view.winbiz.Owners', {
    extend: 'Ext.grid.Panel',
    [...],

    initComponent: function(){
        this.callParent();
        this.on('render', this.loadStore, this);
    },

    loadStore: function() {
        this.getStore().load();
    }
});
Leuco answered 25/10, 2013 at 11:55 Comment(1)
I don't like code in the views. There is no reason to use a controller if you have code that should be the responsibility of the controller in the views. This solution also reloads the store on every render of the view - likely unnecessary?Lalalalage
L
1

I would let the view's controller handle the store load.

Start by disabling autoload on the store.

Ext.define('Mb.controller.Winbiz', {
    extend: 'Ext.app.Controller',
    views: [
        'Owners'
    ],
    ownerStore: null,
    init: function(){
        this.control({
            'menu #test': {click: this.onMenuTest},
        });

        this.ownerStore = Ext.getStore('winbiz.Owners');
    },
    onMenuTest: function() {
        if (this.ownerStore.loaded === false) {
            this.ownerStore.load(
                scope: this,
                callback: this.onOwnerStoreLoaded
            );
        }
        else {
            this.addToTab();
        }            
    },
    onOwnerStoreLoaded: function (store, records, successful, eOpts) {
        if (successful) {
            store.loaded = true;
            this.addToTab();
        }
    },
    addToTab: function () {
        this.getController('Main').addToMainTab('test-gridPanel');
    }

Wheter you want to change the view before or after the store is loaded is another question.

Lalalalage answered 25/10, 2013 at 12:15 Comment(1)
You're right that the code should go into the controller and should not reload the store. Your code is somehow lenghty. I'll try to get it shorter.Joappa
J
0

This is my final controller code:

Ext.define('Mb.controller.Winbiz', {
    extend: 'Ext.app.Controller',
    views: [
        'Owners'
    ],
    refs: [{ref: 'testGrid', selector: 'test-gridPanel'}],
    init: function(){
        this.listen({
            store: {
                '#Owners':{ load: this.onOwnersLoad}
            }
        })
        this.control({
            'menu #test': {click: this.onMenuTest},
            'test-gridPanel': {render: this.onOwnersRender}
        })
    },
    onMenuTest: function(){
        this.getController('Main').addToMainTab('test-gridPanel');
    },
    onOwnersLoad: function(store){
        store.loaded = true
    },
    onOwnersRender: function(){
        var store = this.getTestGrid().getStore();
        if(!store.loaded)store.load();
    },

It puts all code into the controller as suggested by @pcguru and uses the render event to shorten the code as suggested by @Lolo. Thanks

Joappa answered 25/10, 2013 at 12:30 Comment(4)
.loaded is not set in your code, it will always load the store.Lalalalage
@pcguru You're right. So that means there is no way to know if the store is already loaded unless one stores this in a variable on store load ?Joappa
@pcguru I updated my code to correct this problem. Now it's no more shorter than yours :(Joappa
:) But longer code is better if it works correctly and is more reusable and efficient, and especially if it's easier to read and understand than shorter code, imo. One could argue that loaded should be a built-in feature. But one can easily create an override for Ext.data.Store - so you don't have to repeat this for every store - if you do, you can remove the loaded part from this controller.Lalalalage

© 2022 - 2024 — McMap. All rights reserved.