Sencha TouchのストアをAjaxプロキシで正しくロードする

  • 0
    Like
  • 0
    Comment
    More than 1 year has passed since last update.

    インラインデータやlocalstorageのストアをロードするときと比べてajax proxy経由でロードするときはコールバック関数を呼び出す必要がある。

    Controller以外の定義

    AjaxTest.model.Player.js
    Ext.define('AjaxTest.model.Player', {
        extend: 'Ext.data.Model',
    
        config: {
            fields: [
                { name: 'name', type: 'string' },
                { name: 'no', type: 'int' },
                { name: 'position', type: 'string' }
    
            ]
        }
    });
    
    AjaxTest.view.Main.js
    Ext.define('AjaxTest.view.Main', {
        extend: 'Ext.Container',
        xtype: 'main',
        config: {
            tpl: Ext.create('Ext.XTemplate',
                '<tpl>',
                    '<p>{name}</p>',
                '</tpl>'
            ),
        }
    })
    
    AjaxTest.store.Players.js
    Ext.define('AjaxTest.store.Players', {
        extend: 'Ext.data.Store',
        xtype: 'players',
        config: {
            model: 'AjaxTest.model.Player',
            storeId: 'playerStore',
            proxy: {
                type: 'ajax',
                url: 'players.json',
                reader: {
                    type: 'json',
                    rootProperty: 'players'
                }
            },
            autoLoad: true,
        }
    })
    
    players.json
    {
        players: [
            {
                name: "Wayne Rooney",
                no: 10,
                position: "Forward"
            },
            {
                name: "Daren Fletcher",
                no: 24,
                position: "Midfielder"
            }
        ]
    }
    

    ajax proxyじゃない時のロード手順

    インラインやlocalstorageの(上記のplayers.json形式を返す)ストアの場合は、下記のコントローラーでストアを読んでviewへ値を渡せます。

    今回の例ではストアからロードした1番目のnameキーの文字列を返しています。

    AjaxtTest.Controller.Main.js
    Ext.define('AjaxTest.controller.Main', {
        extend: 'Ext.app.Controller',
    
        config: {
            refs: {
                mainView: 'main'
            },
            control: {
                'main': {
                    activate: 'readJson'
                }
            }
        },
    
        readJson: function(){
            var store = Ext.getStore('playerStore');
            var view = this.getMainView();
            store.load();
    
            var name = store.getAt(0).get("name");
            view.setData(
                {
                    name: name,
                }
            ) 
        },
    
        //called when the Application is launched, remove if not needed
        launch: function(app) {
    
        }
    });
    

    これが、今回上記のストアで定義しているようにajaxプロキシ経由で読み込むと次のエラーをはく。

    Uncaught TypeError: Cannot read property 'get' of undefined

    これはajaxプロキシの場合、ストアのロードを非同期で行っているため実際にストアをロードする前に実行しようとしているのでメソッドが見つからないことが原因

    viewにデータを渡すのではなく console.log(store.getCount()) のようにコンソールに値(この場合はストアのサイズ)を表示しようとしてもストアをロードし切る前に実行されてしまうためやっぱりコンソール上には何も表示されない。

    これを回避するためにはloadメソッドの中でコールバック関数を実行してコールバックの中で処理を実行させる必要がある。

    ajax proxy経由の正しいロード手順

    AjaxTest.controller.Main.js
    Ext.define('AjaxTest.controller.Main', {
        extend: 'Ext.app.Controller',
    
        config: {
            refs: {
                mainView: 'main'
            },
            control: {
                'main': {
                    activate: 'readJson'
                }
            }
        },
    
        readJson: function(){
            var store = Ext.getStore('playerStore');
            var view = this.getMainView();
            store.load(function(records, operation, success) {
                var name = store.getAt(0).get('name');
                view.setData({name: name});
            })
            // store.load();
            // store.getAt(0).get("name");
            // view.setData(
            //     {
            //         name: name  ,
            //     }
            // )
        },
    
        //called when the Application is launched, remove if not needed
        launch: function(app) {
    
        }
    });
    

    コールバック関数を使わない時になぜちゃんと動いてくれないのかはこの説明が一番わかりやすかった。

    Can’t Load Record from a Sencha Touch Store?