admin管理员组文章数量:1194540
I am trying to group results that I am getting from store to be displayed inside ComboBox . I have a combobox that looks like this:
and I need it to look like this :
That means grouped by category (order / invoice ).
My combobox defined like this :
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);
}
});
and my data is like this :
[{
"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"
}]
I think that can be done by using Ext.XTemplate
but I am not familiar with Ext.XTemplate
.
I am trying to group results that I am getting from store to be displayed inside ComboBox . I have a combobox that looks like this:
and I need it to look like this :
That means grouped by category (order / invoice ).
My combobox defined like this :
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);
}
});
and my data is like this :
[{
"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"
}]
I think that can be done by using Ext.XTemplate
but I am not familiar with Ext.XTemplate
.
6 Answers
Reset to default 14I wanted a much simpler solution, so I'll share what I came up with.
For my purposes, I had a key
that I wanted to group on, which is a single character. I knew the headers I wanted to show for each key, so I pre-sorted the list to make sure the types came together, and then I just render a group header each time I see a new 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';
}
}
)
});
Using the following 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;
}
And this data:
[
{ 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' }
]
I get a nice looking grouped list like this:
This is an extension that improves on Sean Adkinson answer above by making a reusable component from his code.
I have had mixed results with replacing BoundList with a GridPanel with Ext 5.0.1 there for this is what I used.
One caveat it does not support collapsing the groups but it works great for me.
Tested in Extjs 4.2.3 and 5.0.1.
You can see it in Sencha fiddle
Hope it helps someone out there.
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();
.grouped-list .x-boundlist-item {
padding: 1px 3px 0 10px;
}
.grouped-list .group-header {
padding: 4px;
font-weight: bold;
border-bottom: 1px solid #ddd;
}
Please, you can get this done using a Grid to Render your combobox content. Refer to this post: http://www.sencha.com/forum/showthread.php?132328-CLOSED-ComboBox-using-Grid-instead-of-BoundList
Following the article I was able to create this:
I've implemented my own version of the combo with a grid as its list component. You can get it on GitHub, and I've put some examples online.
The 3rd example closely matches what you're trying to achieve.
Here's an example that would match even more closely. You'd only be left with the styling to do:
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
}]
}
});
That is the code the worked for me:
If you are using Sencha Architect, add the createPicker inside an Override and manually create the listConfig as an 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'
}
Sean Adkinson's answer adapted and working for Ext Js 7.7.0.
See fiddle.
Code:
Ext.application({
name: 'Fiddle',
launch: function () {
//Ext.Msg.alert('Fiddle', 'Welcome to Sencha Fiddle!');
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
items: [{
xtype: 'combo',
fieldLabel: 'SomeCombo',
valueField: 'id',
displayField: 'desc',
tpl: Ext.create('Ext.XTemplate',
// `<ul class="x-list-plain">
// <tpl for=".">
// <li role="option" class="x-boundlist-item">{id} - {desc}</li>
// </tpl></ul>
// `
`{[this.currentKey = null]}
<tpl for=".">
<tpl if="this.shouldShowHeader(gf)">
<div style="font-weight: bold;">{[this.showHeader(values)]}</div>
</tpl>
<div class="x-boundlist-item">{desc}</div>
</tpl>`, {
shouldShowHeader: function (key) {
return this.currentKey != key;
},
showHeader: function (values) {
this.currentKey = values.gf;
return values.gf;
}
}
),
store: {
fields: [{
name: 'id',
type: 'int'
}, {
name: 'gf',
type: 'string'
}, {
name: 'desc',
type: 'string'
}],
data: [{
id: 1,
gf: 'Group 1',
desc: 'Item 1 - 1'
}, {
id: 2,
gf: 'Group 1',
desc: 'Item 1 - 2'
}, {
id: 3,
gf: 'Group 2',
desc: 'Item 2 - 1'
}, {
id: 4,
gf: 'Group 2',
desc: 'Item 2 - 2'
}]
}
}]
});
}
});
本文标签: javascriptEXT 42 ComboBox grouping of results with XTemplateStack Overflow
版权声明:本文标题:javascript - EXT 4.2 ComboBox grouping of results with XTemplate - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738432873a2086509.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论