ExtJs: filtra una cuadrícula con un campo de búsqueda en el encabezado de la columna
Pregunta
En ExtJs, hay muchas opciones para filtrar una cuadrícula.Hay dos buenos ejemplos en la documentación, como se menciona en esta pregunta.
Sin embargo, tener el filtro oculto en el menú desplegable predeterminado de Ext.ux.grid.FiltersFeature
Me parece realmente incómodo.Una buena opción ergonómica sería crear campos de búsqueda en los encabezados de las columnas, como muestra @Ctacus en su pregunta.
¿Cómo se puede lograr esto?
Solución
Después de mucha investigación a través de la escasa documentación, y gracias a excelentes preguntas y respuestas en SO, se me ocurrió una clase simple que agrega esta funcionalidad y permite configuraciones.
Se parece a esto:
Agrega este campo en su cuadrícula de esta manera:
Ext.define('Sandbox.view.OwnersGrid', {
extend: 'Ext.grid.Panel',
requires: ['Sandbox.view.SearchTrigger'],
alias: 'widget.ownersGrid',
store: 'Owners',
columns: [{
dataIndex: 'id',
width: 50,
text: 'ID'
}, {
dataIndex: 'name',
text: 'Name',
items:[{
xtype: 'searchtrigger',
autoSearch: true
}]
},
La siguiente configs
son posibles y funcionan como se describe en el documento para Ext.util.Filter
:
anyMatch
caseSensitive
exactMatch
operator
- además puedes usar
autoSearch
.Si es verdadero, el filtro busca a medida que escribe; si es falso o no está configurado, hay que hacer clic en el icono de búsqueda para aplicar el filtro.
ExtJs 5/6 Fuente:
Ext.define('Sandbox.view.SearchTrigger', {
extend: 'Ext.form.field.Text',
alias: 'widget.searchtrigger',
triggers:{
search: {
cls: 'x-form-search-trigger',
handler: function() {
this.setFilter(this.up().dataIndex, this.getValue())
}
},
clear: {
cls: 'x-form-clear-trigger',
handler: function() {
this.setValue('')
if(!this.autoSearch) this.setFilter(this.up().dataIndex, '')
}
}
},
setFilter: function(filterId, value){
var store = this.up('grid').getStore();
if(value){
store.removeFilter(filterId, false)
var filter = {id: filterId, property: filterId, value: value};
if(this.anyMatch) filter.anyMatch = this.anyMatch
if(this.caseSensitive) filter.caseSensitive = this.caseSensitive
if(this.exactMatch) filter.exactMatch = this.exactMatch
if(this.operator) filter.operator = this.operator
console.log(this.anyMatch, filter)
store.addFilter(filter)
} else {
store.filters.removeAtKey(filterId)
store.reload()
}
},
listeners: {
render: function(){
var me = this;
me.ownerCt.on('resize', function(){
me.setWidth(this.getEl().getWidth())
})
},
change: function() {
if(this.autoSearch) this.setFilter(this.up().dataIndex, this.getValue())
}
}
})
Para ExtJs 6.2.0, el siguiente error y su solución es relevante para esto; de lo contrario, la columna no se puede flex
ed.
ExtJs 4 Fuente:
Ext.define('Sandbox.view.SearchTrigger', {
extend: 'Ext.form.field.Trigger',
alias: 'widget.searchtrigger',
triggerCls: 'x-form-clear-trigger',
trigger2Cls: 'x-form-search-trigger',
onTriggerClick: function() {
this.setValue('')
this.setFilter(this.up().dataIndex, '')
},
onTrigger2Click: function() {
this.setFilter(this.up().dataIndex, this.getValue())
},
setFilter: function(filterId, value){
var store = this.up('grid').getStore();
if(value){
store.removeFilter(filterId, false)
var filter = {id: filterId, property: filterId, value: value};
if(this.anyMatch) filter.anyMatch = this.anyMatch
if(this.caseSensitive) filter.caseSensitive = this.caseSensitive
if(this.exactMatch) filter.exactMatch = this.exactMatch
if(this.operator) filter.operator = this.operator
console.log(this.anyMatch, filter)
store.addFilter(filter)
} else {
store.filters.removeAtKey(filterId)
store.reload()
}
},
listeners: {
render: function(){
var me = this;
me.ownerCt.on('resize', function(){
me.setWidth(this.getEl().getWidth())
})
},
change: function() {
if(this.autoSearch) this.setFilter(this.up().dataIndex, this.getValue())
}
}
})