如何过滤从商店中填充分层数据的Ext.List?

时间:2012-04-10 12:28:25

标签: model sencha-touch store sencha-touch-2 ext.list

问题:

过滤使用商店中的分层数据填充的Ext.List的推荐方法是什么?我需要过滤掉属于我选择过滤的父对象的子对象。孩子们,在这种情况下游戏应该填充列表。

我需要什么

  • Ext.List应该可以循环过滤,即“Omgång1”,“Omgång2”等等。 (瑞典语中的“Omgång”=“Round”)当选择“Omgång1”作为过滤器时,列表应仅显示列表中该轮次的游戏。请参阅下面的JSON文档。
  • 该列表应按日期(“kickOff”)分组,并按“gameId”ASC排序。

我做了什么

  • 创建了一个Ext.List,其中填充了通过Ext.data.Store重新获取的数据,该数据从通过ReST代理读取的JSON文档中获取数据。
  • Ext.List从商店Rounds中读取数据(见下文)。 问题是,我应该只看到一场比赛为“Omgång1”而应该有8场比赛。

这是我迄今为止所取得的成就。使用按钮过滤列表,但只显示其中一个列表项。

Example of the list and the filters.

EM.model.Round

Round的模型。它与Match有一对多的关系。

Ext.define('EM.model.Round', {
extend: 'Ext.data.Model',

init: function() {},

config: {
    storeId: 'Rounds',

    fields: [
        'name', 
        'lockedDate',
    ],
    associations: { 
        type: 'hasMany', 
        model: 'EM.model.Match', 
        primaryKey: 'gameId',
        name: 'matches',
        autoLoad: true,
        associationKey: 'games'
    }   
},
});

EM.model.Match

匹配模型。它属于Round。

Ext.define('EM.model.Match', {
extend: 'Ext.data.Model',

init: function() {},

config: {
    fields: [
        { 
            name: 'gameId', 
            type: 'int'
        }, 
        {
            name: 'firstTeam',
            type: 'string'
        },
        {
            name: 'firstTeamClass',
            type: 'string',

            convert: function(value, record) {
                return util.convertFieldValueToLowerCase('firstTeam', record);
            }
        }, 
        {
            name: 'secondTeam',
            type: 'string'
        },
        {
            name: 'secondTeamClass',
            type: 'string',

            convert: function(value, record) {
                return util.convertFieldValueToLowerCase('secondTeam', record);
            }
        },
        'kickOff',
        {
            name: 'kickOffHour',
            convert: function(value, record) {
                var timestamp = new Date(util.convertUnixTimeToMilliseconds(record.get('kickOff')));

                return Ext.Date.format(timestamp, 'H:i');                   
            }
        },
        { 
            name: 'firstTeamGoals', 
            type: 'int', 
            defaultValue: 0 
         },
        { 
            name: 'secondTeamGoals', 
            type: 'int', 
            defaultValue: 0 
         },          
        { 
            name: 'firstTeamGoalsBet', 
         }, 
        { 
            name: 'secondTeamGoalsBet', 
         },
        'points',
        {
            name: 'pointsEarned',
            convert: function(value, record) {
                var className = 'no-points-earned';
                var points = record.get('points'); 

                if (typeof points == 'undefined') {
                    return '';
                }

                if (points > 0) {
                    className = 'points-earned';
                }

                return '<div class="' + className + '">' + points + '</div>'
            }
        },
    ],

    associations: {
        type: 'belongsTo',
        model: 'EM.model.Round',
        name: 'round',
        autoLoad: true
    }

}
});

EM.store.Rounds

读取JSON文档的商店。然后使用此存储来填充Ext.List。

Ext.define('EM.store.Rounds', {
extend: 'Ext.data.Store',

config: {
    model: 'EM.model.Round',
    storeId: 'Rounds',
    filters: [{
        property: 'name',
        value: 'Round 1'
    }],
    /*grouper: {
        groupFn: function (item) {
            //var kickOff = new Date(util.convertUnixTimeToMilliseconds(item.get('kickOff')));
            //return kickOff.format('d mmmm yyyy');
        },
        //sortProperty: 'kickOff'
    },*/        
    proxy: {
        type: 'rest',
        url : 'resources/json/matches.json',
        reader: {
            type: 'json',
        }
    },
    autoLoad: true,
}
});

JSON文档

这是 EM.store.Rounds 中代理读取的JSON文档。

[
{   
    "name": "Omgång 1",
    "lockedDate": 1325420111,
    "games": [
        {
            "gameId": 1,
            "firstTeam": "Pol",
            "secondTeam": "Gre",
            "kickOff": 1339178400,
            "firstTeamGoals": 0,
            "secondTeamGoals": 3,
            "firstTeamGoalsBet": 0,
            "secondTeamGoalsBet": 3,
            "points": 3
        },
        {
            "gameId": 2,
            "firstTeam": "Rus",
            "secondTeam": "Cze",
            "kickOff": 1339188300,
            "firstTeamGoals": 4,
            "secondTeamGoals": 1,
            "firstTeamGoalsBet": 1,
            "secondTeamGoalsBet": 2,
            "points": 0
        },{
            "gameId": 3,
            "firstTeam": "Ned",
            "secondTeam": "Den",
            "kickOff": 1339264800,
            "firstTeamGoals": 2,
            "secondTeamGoals": 1,
            "firstTeamGoalsBet": 4,
            "secondTeamGoalsBet": 2,
            "points": 2
        },
        {
            "gameId": 4,
            "firstTeam": "Ger",
            "secondTeam": "Por",
            "firstTeamGoalsBet": 4,
            "secondTeamGoalsBet": 0,
            "kickOff": 1339274700
        },
        {
            "gameId": 5,
            "firstTeam": "Spa",
            "secondTeam": "Ita",
            "firstTeamGoalsBet": 3,
            "secondTeamGoalsBet": 2,
            "kickOff": 1339351200
        },  
        {
            "gameId": 6,
            "firstTeam": "Irl",
            "secondTeam": "Cro",
            "kickOff": 1339361100
        },
        {
            "gameId": 7,
            "firstTeam": "Fra",
            "secondTeam": "Eng",
            "kickOff": 1339437600
        },
                    {
            "gameId": 8,
            "firstTeam": "Ukr",
            "secondTeam": "Swe",
            "kickOff": 1339447500
        }
    ]
},
{
     "name": "Omgång 2",
     "games": [
         {
            "gameId": 4,
            "firstTeam": "Gre",
            "secondTeam": "Cze",
            "kickOff": 1339524000
        }
     ]
},
{
     "name": "Omgång 3",
     "games": [
         {
            "gameId": 4,
            "firstTeam": "Gre",
            "secondTeam": "Rus",
            "kickOff": 1339869600
        }
     ]
},
{
     "name": "Kvart",
     "games": [
         {
            "gameId": 4,
            "firstTeam": "1A",
            "secondTeam": "2B",
            "kickOff": 1340311500
        }
     ]
},
{
     "name": "Semi",
     "games": [
         {
            "gameId": 4,
            "firstTeam": "#25",
            "secondTeam": "#27",
            "kickOff": 1340829900
        }
     ]
},
{
     "name": "Final",
     "games": [
         {
            "gameId": 4,
            "firstTeam": "#29",
            "secondTeam": "#30",
            "kickOff": 1341175500
        }
     ]
}
]

EM.view.MatchList

显示匹配列表的列表视图。

Ext.define('EM.view.MatchList', {
extend: 'Ext.List',
xtype: 'matchlist',

requires: [
    'Ext.TitleBar',
    'EM.store.Rounds'
],

config: {
    id: 'match-list',       
    store: 'Rounds',
    //grouped: true,
    scrollable: false,

    items: [
        {
            xtype: 'titlebar',

            scrollable: {
                direction: 'horizontal',
                directionLock: true
            },

            items: [
                {
                    xtype: 'button',
                    text: 'Omgång 1',
                    handler: function() {
                        var sto = Ext.getStore('Rounds');
                        sto.clearFilter();
                        sto.filter('name', 'Omgång 1');
                        console.log(sto);
                    }
                },
                {
                    xtype: 'button',                        
                    text: 'Omgång 2',
                    handler: function() {
                        var sto = Ext.getStore('Rounds');
                        sto.clearFilter();
                        sto.filter('name', 'Omgång 2');

                    }
                },
                {
                    xtype: 'button',
                    text: 'Omgång 3',
                    handler: function() {
                        var sto = Ext.getStore('Rounds');
                        sto.clearFilter();
                        sto.filter('name', 'Omgång 3');

                    }
                },
                {
                    xtype: 'button',                        
                    text: 'Kvart',
                    handler: function() {
                        var sto = Ext.getStore('Rounds');
                        sto.clearFilter();
                        sto.filter('name', 'Kvart');

                    }
                },
                {
                    xtype: 'button',                        
                    text: 'Semi',
                    handler: function() {
                        var sto = Ext.getStore('Rounds');
                        sto.clearFilter();
                        sto.filter('name', 'Semi');

                    }
                },
                {
                    xtype: 'button',                        
                    text: 'Final',
                    handler: function() {
                        var sto = Ext.getStore('Rounds');
                        sto.clearFilter();
                        sto.filter('name', 'Final');

                    }
                }                           

            ],
        },
        {
            xtype: 'panel',
            html: 'Senast uppdaterad: Idag kl 20:12'
        }
    ],

    itemTpl: [

        '<div class="match-meta-data">',
        '<tpl for="matches">',          
            '<div class="team-wrapper home-team">{firstTeam} <div class="flag {firstTeamClass}"><span></span></div> <span class="goals-scored">{firstTeamGoals}</span></div>',
            '<div class="kick-off-time">{kickOffHour}</div>',
            '<div class="team-wrapper away-team"><span class="goals-scored">{secondTeamGoals}</span> <div class="flag {secondTeamClass}"><span></span></div> {secondTeam}</div>',
            '<div class="bet-meta-data">',
                '<img class="user-icon" src="resources/images/user-22x26.png" />',
                '<div class="home-team goals-bet">{firstTeamGoalsBet}</div>',
                '<div class="away-team goals-bet">{secondTeamGoalsBet}</div>',
                '{pointsEarned}',   
            '</div>',
        '</tpl>',
        '</div>',

        ].join('')
    },

});

这是我的第一个Sencha Touch应用,所以请随时指出您在代码中看到的任何不良做法。有人可以提供一个如何实现我的目标的例子吗?我花了很多时间试图弄清楚这个。

完整项目可以从https://github.com/eriktoyra/EM-Tipset的GitHub下载。最新的分支是_filter-match-list。

2 个答案:

答案 0 :(得分:0)

这些确实是两个问题。我不知道为什么你的整个商店似乎没有在列表视图中呈现;一些踩踏和暂停可能会对此有所了解。如果您在某个地方举办过演示,我很乐意看一下。

关于你的多轮过滤问题,我现在可以想到两件事:

  • 据我所知,对商店执行filter操作会导致它“丢失”数据,即丢弃与过滤器不匹配的所有数据(而不是将其隐藏在存储器中) )。如果您在同一服务器调用中将所有轮次加载到一个商店中,我不确定过滤是否适合您。我可能错了,但我只是尝试从Javascript控制台中过滤我的一个应用程序中的商店;当我应用了一个与任何项目都不匹配的过滤器时,商店就会清空。基于此,过滤可能不是最好的事情。

  • 为每轮创建一个单独的listview,每个轮次使用相同的公共轮次存储。使用itemTpl配置和XTemplate来确定哪些匹配应该放入每个列表中。根据需要,使用Omgång按钮从视口中交换这些列表。

在更好地了解您的问题和代码后更新答案

答案 1 :(得分:0)

我设法通过使用类似于我的实际测试场景来找到解决此问题的方法。

解决方案

我做的是:

  1. 让Division模型处理代理并从 match.json 读取数据,而不是让Division存储读取数据。
  2. 设置分部和团队模型之间的关系,以便彼此了解。
  3. 设置两个商店。一个用于分区,一个用于团队。在加载Division商店时,我使用回调来使用来自Division商店的Team数据填充Team商店。
  4. 然后我用Team商店填充了列表,Team商店有Team对象,现在知道他们对Division模型/商店的引用。
  5. 通过查找列表中每个Team项的Division对象并将Division的 name 属性与过滤器提供的属性进行比较来完成实际过滤。
  6. 下面提供了完整的解决方案,也可以在GitHub上找到。

    如果其他人应该找到更好的解决方案或指出一些改进,我会在几天内保持这个问题没有答案。

        /**
         * @description The main purpose of this mockup is to test how to filter a list using hierarchical data. The code is adapted from the example 
         * "Filtering data in an Ext.List component in Sencha Touch 2" by Peter deHaan.  
         * @see <a href="http://senchaexamples.com/2012/03/15/filtering-data-in-an-ext-list-component-in-sencha-touch-2/">Filtering data in an Ext.List component in Sencha Touch 2</a>.
         * @author <a href="mailto:erik.toyra[at]gmail.com">Erik Töyrä</a>      
         */
        Ext.application({
            launch: function () {
                /**
                 * Division model
                 */
                Ext.define("Division", {
                    extend: 'Ext.data.Model',
                    config: {
                        fields: [
                            'division'
                        ],
                        // Setup a hasMany relations between Division and Team
                        hasMany: {model: 'Team', name: 'teams'},
    
                        // Load data from teams.json into the Division model
                        proxy: {
                            type: 'rest',
                            url : 'teams.json',
                            reader: {
                                type: 'json'
                            }
                        }
                    }
                });
    
                /**
                 * Team model
                 */
                Ext.define("Team", {
                    extend: 'Ext.data.Model',
                    config: {
                        fields: [
                            'name', 'league'
                        ],
                        // Setup a belongsTo relationship between Team and Division
                        belongsTo: {model: 'Division'},
                    }
                });                
    
                /**
                 * Division store
                 */
                var divisionStore = Ext.create('Ext.data.Store', {
                    model: "Division",
                    storeId: 'divisionStore',
                });
    
                /**
                 * Team store
                 */
                var teamStore = Ext.create('Ext.data.Store', {
                    model: "Team",
                    storeId: 'teamStore', // This is the store we will reference in our Ext.list below.
                    fields: ['division', 'leage', 'name'],
                });
    
                /**
                 * Load the Division store which holds all of the data read from teams.json. 
                 * After the data has been loaded we add the team data to the teamStore.
                 */
                divisionStore.load({
                    callback: function() {
                        // Loop through each division and retrieve the all teams that resides as 
                        // childs to the division. Then we add each team to the teamStore.
                        divisionStore.each(function(division) {
                            division.teams().each(function(team) {
                                teamStore.add(team);
                            });
                        });
                    }
                });
    
                /**
                 * Create the list that should be filtered by Division and display a filtered list with Team objects.
                 */
                Ext.create('Ext.List', {
                    fullscreen: true,
    
                    items: [{
                        xtype: 'titlebar',
                        docked: 'top',
                        ui: 'neutral',
    
                        items: [{
                            text: 'West only',
                            handler: function () {
                                return util.doFilter('West');
                            } // handler
                        }, {
                            text: 'Central only',
                            handler: function () {
                                return util.doFilter('Central');
                            } // handler
                        }, {
                            text: 'East only',
                            handler: function () {
                                return util.doFilter('East');                               
                            } // handler
                        }, {
                            text: 'Clear filters',
                            ui: 'decline',
                            align: 'right',
                            handler: function () {
                                Ext.getStore('teamStore').clearFilter();
                            } // handler
                        }
                        ] // items (toolbar)
                    }], // items (list)
                    store: 'teamStore',
                    itemTpl: '{name}, {league}',
                }); // create()
    
    
                /**
                 * Utility functions
                 */
                var util = (function() {
                    var util = {};
    
                    /**
                     * Filter the teamStore by the passed in Division name.
                     */
                    util.doFilter = function(filterOption) {
                        var store = Ext.getStore('teamStore');
    
                        // Clear all existing filters first...
                        store.clearFilter();
    
                        // ... then apply the selected filter
                        store.filterBy(function(record, id) {
                                return record.getDivision().get('division') == filterOption;
                            }, this);
                    }
    
                    return util;
                })();
            } // launch
        }); // application()
    

    JSON数据

    [
    {
        division: 'East',
        teams: [
            {
                name: 'New York Yankees',
                league: 'AL',
            }, {
                name: 'Tampa Bay',
                league: 'AL',
            }, {
                name: 'Boston',
                league: 'AL',
            }, {
                name: 'Toronto',
                league: 'AL',
            }, {
                name: 'Baltimore',
                league: 'AL',
            }
        ]
    },
    {
        division: 'Central',
        teams: [
            {
                name: 'Detroit',
                league: 'AL',
    
            }, {
                name: 'Cleveland',
                league: 'AL',
            }, {
                name: 'Chicago White Sox',
                league: 'AL',
            }, {
                name: 'Kansas City',
                league: 'AL',
            }, {
                name: 'Minnesota',
                league: 'AL',
            }                            
        ]
    },
    {
        division: 'West',
        teams: [
        {
                name: 'Texas',
                league: 'AL',
            }, {
                name: 'Los Angeles Angels',
                league: 'AL',
            }, {
                name: 'Oakland',
                league: 'AL',
            }, {
                name: 'Seattle',
                league: 'AL',
            }
        ]
    }
    ]