我正在尝试将我从商店获得的结果分组到ComboBox中。 我有一个看起来像这样的组合框:
我需要它看起来像这样:
这意味着按类别(订单/发票)分组。
我的组合框定义如下:
Ext.define('NG.view.searchcombo.Combo', {
requires: ['Ext.form.field.ComboBox'],
extend: 'Ext.form.ComboBox',
alias: 'widget.searchcombo',
minChars:3,
fieldLabel: 'Choose Search',
store: 'Search',
displayField: 'name',
valueField: 'id',
typeAhead: false,
hideLabel: true,
hideTrigger:false,
anchor: '100%',
listConfig: {
loadingText: 'Searching...',
emptyText: 'No matching posts found.',
// Custom rendering template for each item
getInnerTpl: function() {
return '<h3>{name} / {category}</h3>' +'{excerpt}' ;
}
},
pageSize: 10,
initComponent: function () {
this.callParent(arguments);
}
});
我的数据是这样的:
[{
"id": 1,
"name": "one",
"category": "invoice"
}, {
"id": 2,
"name": "two",
"category": "invoice"
}, {
"id": 3,
"name": "one",
"category": "order"
}, {
"id": 4,
"name": "two",
"category": "order"
}, {
"id": 5,
"name": "three",
"category": "invoice"
}, {
"id": 6,
"name": "four",
"category": "invoice"
}, {
"id": 7,
"name": "three",
"category": "order"
}, {
"id": 8,
"name": "four",
"category": "order"
}, {
"id": 9,
"name": "five",
"category": "invoice"
}, {
"id": 10,
"name": "six",
"category": "invoice"
}, {
"id": 11,
"name": "five",
"category": "order"
}, {
"id": 12,
"name": "six",
"category": "order"
}, {
"id": 13,
"name": "seven",
"category": "invoice"
}, {
"id": 14,
"name": "eight",
"category": "invoice"
}, {
"id": 15,
"name": "seven",
"category": "order"
}, {
"id": 16,
"name": "eight",
"category": "order"
}]
我认为可以使用Ext.XTemplate
来完成,但我不熟悉Ext.XTemplate
。
答案 0 :(得分:10)
我想要一个更简单的解决方案,所以我将分享我的想法。
出于我的目的,我有一个key
我想要分组,这是一个单个字符。我知道我想为每个键显示的标题,所以我预先对列表进行排序以确保类型组合在一起,然后每次看到新键时我只渲染一个组标题。
myStore.sort('key', 'DESC');
Ext.create('Ext.form.field.ComboBox', {
store: myStore,
queryMode: 'local',
displayField: 'name',
valueField: 'id',
listConfig: {
cls: 'grouped-list'
},
tpl: Ext.create('Ext.XTemplate',
'{[this.currentKey = null]}' +
'<tpl for=".">',
'<tpl if="this.shouldShowHeader(key)">' +
'<div class="group-header">{[this.showHeader(values.key)]}</div>' +
'</tpl>' +
'<div class="x-boundlist-item">{name}</div>',
'</tpl>',
{
shouldShowHeader: function(key){
return this.currentKey != key;
},
showHeader: function(key){
this.currentKey = key;
switch (key) {
case 's': return 'Structures';
case 'f': return 'Filters';
...
}
return 'Other';
}
}
)
});
使用以下CSS:
.grouped-list .x-boundlist-item {
padding: 1px 3px 0 10px
}
.grouped-list .group-header {
padding: 4px;
font-weight: bold;
border-bottom: 1px solid #ddd;
}
这个数据:
[
{ key: 's', name: '2014 Product Development' },
{ key: 'f', name: 'Message Filter' },
{ key: 's', name: '2014 Product Development (Little)' },
{ key: 's', name: 'Global Structure' },
{ key: 'f', name: 'My SW' }
]
我得到了一个漂亮的分组列表,如下所示:
答案 1 :(得分:6)
这是一个扩展,通过从他的代码中创建一个可重用的组件来改进Sean Adkinson的回答。
我有一个混合的结果,用一个带有Ext 5.0.1的GridPanel替换BoundList,这就是我使用的。
有一点需要注意,它不支持折叠群体,但它对我来说很有用。
在Extjs 4.2.3和5.0.1中测试。
你可以在Sencha fiddle
中看到它希望它可以帮助那些人。
Ext.define('Ext.ux.GroupComboBox', {
extend: 'Ext.form.field.ComboBox',
alias: 'widget.groupcombobox',
/*
* @cfg groupField String value of field to groupBy, set this to any field in your model
*/
groupField: 'group',
listConfig: {
cls: 'grouped-list'
},
initComponent: function() {
var me = this;
me.tpl = new Ext.XTemplate([
'{%this.currentGroup = null%}',
'<tpl for=".">',
' <tpl if="this.shouldShowHeader(' + me.groupField + ')">',
' <div class="group-header">{[this.showHeader(values.' + me.groupField + ')]}</div>',
' </tpl>',
' <div class="x-boundlist-item">{' + me.displayField + '}</div>',
'</tpl>', {
shouldShowHeader: function(group) {
return this.currentGroup != group;
},
showHeader: function(group) {
this.currentGroup = group;
return group;
}
}
]);
me.callParent(arguments);
}
});
//Example usage
var Restaurants = Ext.create('Ext.data.Store', {
storeId: 'restaraunts',
fields: ['name', 'cuisine'],
sorters: ['cuisine', 'name'],
groupField: 'cuisine',
data: [{
name: 'Cheesecake Factory',
cuisine: 'American'
}, {
name: 'University Cafe',
cuisine: 'American'
}, {
name: 'Creamery',
cuisine: 'American'
}, {
name: 'Old Pro',
cuisine: 'American'
}, {
name: 'Nola\'s',
cuisine: 'Cajun'
}, {
name: 'House of Bagels',
cuisine: 'Bagels'
}, {
name: 'The Prolific Oven',
cuisine: 'Sandwiches'
}, {
name: 'La Strada',
cuisine: 'Italian'
}, {
name: 'Buca di Beppo',
cuisine: 'Italian'
}, {
name: 'Pasta?',
cuisine: 'Italian'
}, {
name: 'Madame Tam',
cuisine: 'Asian'
}, {
name: 'Sprout Cafe',
cuisine: 'Salad'
}, {
name: 'Pluto\'s',
cuisine: 'Salad'
}, {
name: 'Junoon',
cuisine: 'Indian'
}, {
name: 'Bistro Maxine',
cuisine: 'French'
}, {
name: 'Three Seasons',
cuisine: 'Vietnamese'
}, {
name: 'Sancho\'s Taquira',
cuisine: 'Mexican'
}, {
name: 'Reposado',
cuisine: 'Mexican'
}, {
name: 'Siam Royal',
cuisine: 'Thai'
}, {
name: 'Krung Siam',
cuisine: 'Thai'
}, {
name: 'Thaiphoon',
cuisine: 'Thai'
}, {
name: 'Tamarine',
cuisine: 'Vietnamese'
}, {
name: 'Joya',
cuisine: 'Tapas'
}, {
name: 'Jing Jing',
cuisine: 'Chinese'
}, {
name: 'Patxi\'s Pizza',
cuisine: 'Pizza'
}, {
name: 'Evvia Estiatorio',
cuisine: 'Mediterranean'
}, {
name: 'Gyros-Gyros',
cuisine: 'Mediterranean'
}, {
name: 'Mango Caribbean Cafe',
cuisine: 'Caribbean'
}, {
name: 'Coconuts Caribbean Restaurant & Bar',
cuisine: 'Caribbean'
}, {
name: 'Rose & Crown',
cuisine: 'English'
}, {
name: 'Baklava',
cuisine: 'Mediterranean'
}, {
name: 'Mandarin Gourmet',
cuisine: 'Chinese'
}, {
name: 'Bangkok Cuisine',
cuisine: 'Thai'
}, {
name: 'Darbar Indian Cuisine',
cuisine: 'Indian'
}, {
name: 'Mantra',
cuisine: 'Indian'
}, {
name: 'Janta',
cuisine: 'Indian'
}, {
name: 'Starbucks',
cuisine: 'Coffee'
}, {
name: 'Peet\'s Coffee',
cuisine: 'Coffee'
}, {
name: 'Coupa Cafe',
cuisine: 'Coffee'
}, {
name: 'Lytton Coffee Company',
cuisine: 'Coffee'
}, {
name: 'Il Fornaio',
cuisine: 'Italian'
}, {
name: 'Lavanda',
cuisine: 'Mediterranean'
}, {
name: 'MacArthur Park',
cuisine: 'American'
}, {
name: 'St Michael\'s Alley',
cuisine: 'Californian'
}, {
name: 'Cafe Renzo',
cuisine: 'Italian'
}, {
name: 'Miyake',
cuisine: 'Sushi'
}, {
name: 'Sushi Tomo',
cuisine: 'Sushi'
}, {
name: 'Kanpai',
cuisine: 'Sushi'
}, {
name: 'Pizza My Heart',
cuisine: 'Pizza'
}, {
name: 'New York Pizza',
cuisine: 'Pizza'
}, {
name: 'Loving Hut',
cuisine: 'Vegan'
}, {
name: 'Garden Fresh',
cuisine: 'Vegan'
}, {
name: 'Cafe Epi',
cuisine: 'French'
}, {
name: 'Tai Pan',
cuisine: 'Chinese'
}]
});
Ext.create('Ext.container.Viewport', {
items: Ext.create('Ext.ux.GroupComboBox', {
fieldLabel: 'Restaurants',
name: 'txtRestaurant',
forceSelection: true,
editable: false,
queryMode: 'local',
triggerAction: 'all',
multiSelect: true,
groupField: 'cuisine',
displayField: 'name',
valueField: 'name',
store: Restaurants,
width: 400
})
}).show();
&#13;
.grouped-list .x-boundlist-item {
padding: 1px 3px 0 10px;
}
.grouped-list .group-header {
padding: 4px;
font-weight: bold;
border-bottom: 1px solid #ddd;
}
&#13;
答案 2 :(得分:1)
请你,你可以使用Grid来渲染你的组合框内容。请参阅此帖:http://www.sencha.com/forum/showthread.php?132328-CLOSED-ComboBox-using-Grid-instead-of-BoundList
在文章之后,我能够创建:
答案 3 :(得分:0)
这就是为我工作的代码:
如果您使用的是Sencha Architect,请在Override中添加createPicker,并手动将listConfig创建为Object。
{
xtype: 'combobox',
createPicker: function() {
var me = this,
picker,
menuCls = Ext.baseCSSPrefix + 'menu',
opts = Ext.apply({
selModel: {
mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
},
floating: true,
hidden: true,
ownerCt: me.ownerCt,
cls: me.el.up('.' + menuCls) ? menuCls : '',
store: me.store,
displayField: me.displayField,
focusOnToFront: false,
pageSize: me.pageSize
}, me.listConfig, me.defaultListConfig);
// NOTE: we simply use a grid panel
//picker = me.picker = Ext.create('Ext.view.BoundList', opts);
picker = me.picker = Ext.create('Ext.grid.Panel', opts);
// hack: pass getNode() to the view
picker.getNode = function() {
picker.getView().getNode(arguments);
};
me.mon(picker.getView(), {
refresh: me.onListRefresh,
scope: me
});
me.mon(picker, {
itemclick: me.onItemClick,
// refresh: me.onListRefresh,
scope: me
});
me.mon(picker.getSelectionModel(), {
selectionChange: me.onListSelectionChange,
scope: me
});
return picker;
},
listConfig: {
columns: [{
xtype: "gridcolumn",
dataIndex: "id",
text: "Id"
}, {
xtype: "gridcolumn",
dataIndex: "name",
text: "Name"
}],
features: [{
ftype: "grouping"
}]
},
fieldLabel: 'Label',
queryMode: 'local',
store: 'myTestStore'
}
答案 4 :(得分:0)
我已经使用网格作为列表组件实现了我自己的组合版本。你可以在GitHub上获得它,我已经放了一些examples online。
第三个例子与你想要达到的目标非常吻合。
这是一个更紧密匹配的例子。你只能留下造型:
Ext.widget('gridpicker', {
queryMode: 'local'
,displayField: 'name'
,store: {
fields: ['name', 'group']
,proxy: {type: 'memory', reader: 'array'}
,data: ...
,groupField: 'group'
,sorters: {property: 'name', order: 'ASC'}
}
,gridConfig: {
features: [{
ftype:'grouping'
,groupHeaderTpl: '{name}'
,collapsible: false
}]
,columns: [{
width: 30
,renderer: function(value, md, record, rowIndex) {
return '<img src="..." />';
}
},{
dataIndex: 'name'
,flex: 1
}]
}
});