javascript - Agrupación de resultados de EXT 4.2 ComboBox con XTemplate
extjs grouping (5)
Esta es una extensión que mejora la respuesta anterior de Sean Adkinson al hacer un componente reutilizable de su código.
He tenido resultados mixtos al reemplazar BoundList con un GridPanel con Ext 5.0.1 allí porque esto es lo que usé.
Una advertencia: no es compatible con el colapso de los grupos, pero funciona muy bien para mí.
Probado en Extjs 4.2.3 y 5.0.1.
Puedes verlo en Sencha violín
Espero que ayude a alguien por ahí.
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;
}
Estoy tratando de agrupar los resultados que obtengo de la tienda para que se muestren dentro de ComboBox. Tengo un combobox que se ve así:
y necesito que se vea así:
Eso significa agrupado por categoría (orden / factura).
Mi cuadro combinado definido así:
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);
}
});
y mis datos son así:
[{"id": 1, "nombre": "uno", "categoría": "factura"}, {"id": 2, "nombre": "dos", "categoría": "factura"}, { "id": 3, "nombre": "uno", "categoría": "orden"}, {"id": 4, "nombre": "dos", "categoría": "orden"}, {"id ": 5," nombre ":" tres "," categoría ":" factura "}, {" id ": 6," nombre ":" cuatro "," categoría ":" factura "}, {" id ": 7, "nombre": "tres", "categoría": "orden"}, {"id": 8, "nombre": "cuatro", "categoría": "orden"}, {"id": 9, "nombre": "cinco", "categoría": "factura"}, {"id": 10, "nombre": "seis", "categoría": "factura"}, {"id": 11, "nombre ":" cinco "," categoría ":" orden "}, {" id ": 12," nombre ":" seis "," categoría ":" orden "}, {" id ": 13," nombre ": "siete", "categoría": "factura"}, {"id": 14, "nombre": "ocho", "categoría": "factura"}, {"id": 15, "nombre": "siete "," categoría ":" orden "}, {" id ": 16," nombre ":" ocho "," categoría ":" orden "}]
Creo que se puede hacer utilizando Ext.XTemplate, pero no estoy familiarizado con Ext.XTemplate.
Por favor, puede hacer esto usando una Cuadrícula para Renderizar su contenido de combobox. Consulte esta publicación: http://www.sencha.com/forum/showthread.php?132328-CLOSED-ComboBox-using-Grid-instead-of-BoundList
Siguiendo el artículo, pude crear esto:
Ese es el código que funcionó para mí: si está usando Sencha Architect, agregue el createPicker dentro de Override y cree manualmente el listConfig como un 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''
}
Implementé mi propia versión del combo con una grilla como su componente de lista. Puedes obtenerlo en GitHub , y he puesto algunos ejemplos en línea .
El tercer ejemplo se aproxima mucho a lo que estás tratando de lograr.
Aquí hay un ejemplo que coincidiría aún más de cerca. Solo te quedaría el estilo para hacer:
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
}]
}
});
Quería una solución mucho más simple, así que compartiré lo que se me ocurrió.
Para mis propósitos, tenía una key
que quería agrupar, que es un solo personaje. Sabía los encabezados que quería mostrar para cada clave, por lo que ordené previamente la lista para asegurarme de que los tipos se unieran, y luego simplemente represento un encabezado de grupo cada vez que veo una nueva clave.
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'';
}
}
)
});
Usando el siguiente 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;
}
Y esta información:
[
{ 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'' }
]
Obtengo una bonita lista agrupada como esta: