Live Search on Grid --ExtJs - extjs

I am new to ExtJs, and i am playing around to build logic to perform "live search" on Grid columns.
From the code below i am able to populate data into the grid but cannot make live search functionality. i am not sure where i am missing the logic.
Ext.define('abc.view.EmployeePanel', {
extend: 'Ext.window.Window',
alias: 'widget.EmployeePanel',
requires: [
'Ext.tab.Panel',
'Ext.form.*'],
constructor: function () {
this.callParent(arguments);
},
this. employeePopUPGridStore = new Ext.data.ArrayStore({
fields: [
{
name: 'empid',
type: 'number'
},
{
name: 'fname',
type: 'string'
},
{
name: 'lname',
type: 'string'
},
],
});
this.employeePopUPGridStore.loadData(localAr, false);
this.down('#addempgrid').bindStore(this.employeePopUPGridStore);
this.down('#addempgrid').getView().refresh();
},
items: [{
xtype:'textfield',
name:'search',
itemId:'search',
emptyText:'Search by First Name / Last Name',
listeners: {
onTextFieldChange: function(field, newValue, oldValue, eOpts){
var grid = field.down('addempgrid');
grid.store.clearFilter();
if (newValue) {
var matcher = new RegExp(Ext.String.escapeRegex(newValue), "i");
grid.store.filter({
filterFn: function(item) {
return matcher.test(item.get('empid')) ||
matcher.test(item.get('fname')) ||
matcher.test(item.get('job'));
}
});
}
}
}
},
{
xtype: 'gridpanel',
itemId: 'addempgrid',
autoHeight: true,
columns: [
{
header: "Employee ID",
flex: 1,
dataIndex: 'empid',
},
{
header: "Full Name",
flex: 3,
dataIndex: 'fname'
},
{
header: "LastName",
flex: 1,
dataIndex: 'lname'
},
]
}
] }
});
Any help around is much appreciated.

Hi Please try this way once..
{
xtype: 'textfield',
itemId: 'searchBar',
cls: 'search-bar',
width: 230,
margin: '0 0 0 10',
listeners: {
buffer: 250,
scope: this,
change: function (field, newVal) {
var grid = field.down('addempgrid');
grid.store.clearFilter();
if (newValue) {
var matcher = new RegExp(Ext.String.escapeRegex(newValue), "i");
grid.store.filter({
filterFn: function(item) {
return matcher.test(item.get('empid')) ||
matcher.test(item.get('fname')) ||
matcher.test(item.get('job'));
}
});
}
}
}
}
Hope it helps you

Related

Ext js 7 modern grid plugin RowExpander only certain rows

I'm trien to use the RowExpander plugin for Ext js 7 modern grid.
I need the RowExpander only on a few rows, not on all.
I'm not sure how to achieve this, I searched for some examples but they are all for ext js 4.
I tried overriding
applyColumn: function(column, oldColumn) {
console.log('override applyColumn:');
console.log(column);
return Ext.factory(Ext.apply({}, column), null, oldColumn);
},
updateGrid: function(grid) {
var me = this;
console.log('override test:');
console.log(grid);
if (grid) {
grid.hasRowExpander = true;
grid.addCls(Ext.baseCSSPrefix + 'has-rowexpander');
me.colInstance = grid.registerColumn(me.getColumn());
grid.refreshScrollerSize();
grid.element.on({
tap: 'onGridTap',
delegate: me.expanderSelector,
scope: me
});
}
},
But i cant "hook into a single row" when data is there.
Looking for something like this but for ext js 7 modern grid:
How can I get the ExtJs RowExpander to only show the icon ([+]) on certain rows?
You can bind the 'hidden', something like this:
Ext.define('Ext.grid.plugin.CustomRowExpander', {
extend: 'Ext.plugin.Abstract',
requires: [
'Ext.grid.cell.Expander'
],
alias: 'plugin.customrowexpander',
config: {
grid: null,
column: {
weight: -1100,
xtype: 'gridcolumn',
align: 'center',
text: '',
width: 50,
resizable: false,
hideable: false,
sortable: false,
editable: false,
ignore: true,
ignoreExport: true,
cell: {
xtype: 'expandercell',
hideMode: 'opacity',
bind: {
hidden: '{record.expandable}'
}
},
menuDisabled: true
}
},
expanderSelector: '.' + Ext.baseCSSPrefix + 'expandercell .' + Ext.baseCSSPrefix + 'icon-el',
init: function (grid) {
grid.setVariableHeights(true);
this.setGrid(grid);
},
destroy: function () {
var grid = this.getGrid(),
col = this.colInstance;
if (col && !grid.destroying) {
grid.unregisterColumn(col, true);
}
this.callParent();
},
applyColumn: function (column, oldColumn) {
return Ext.factory(Ext.apply({}, column), null, oldColumn);
},
updateGrid: function (grid) {
var me = this;
if (grid) {
grid.hasRowExpander = true;
grid.addCls(Ext.baseCSSPrefix + 'has-rowexpander');
me.colInstance = grid.registerColumn(me.getColumn());
grid.refreshScrollerSize();
grid.element.on({
tap: 'onGridTap',
delegate: me.expanderSelector,
scope: me
});
}
},
onGridTap: function (e) {
var cell = Ext.Component.from(e),
row = cell.row;
// May have tapped on a descendant grid row. We're only interested in our own.
if (row.getGrid() === this.getGrid()) {
row.toggleCollapsed();
}
}
});
Ext.application({
name: 'Fiddle',
launch: function () {
var store = Ext.create('Ext.data.Store', {
fields: ['fname', 'lname', 'talent', 'powers'],
data: [{
'fname': 'Barry',
'lname': 'Allen',
'talent': 'Speedster',
'expandable': true
}, {
'fname': 'Oliver',
'lname': 'Queen',
'talent': 'Archery',
'expandable': false
}, {
'fname': 'Kara',
'lname': 'Zor-El',
'talent': 'All',
'expandable': true
}, {
'fname': 'Helena',
'lname': 'Bertinelli',
'talent': 'Weapons Expert',
'expandable': false
}, {
'fname': 'Hal',
'lname': 'Jordan',
'talent': 'Willpower',
'expandable': true
}, ]
});
Ext.create('Ext.grid.Grid', {
title: 'DC Personnel',
store: store,
plugins: {
customrowexpander: true
},
itemConfig: {
viewModel: true,
body: {
tpl: '<div>Lorem ipsum dolor sit amet, consetetur sadipscing elitr..</div>'
}
},
columns: [{
text: 'First Name',
dataIndex: 'fname',
flex: 1
}, {
text: 'Last Name',
dataIndex: 'lname',
flex: 1
}, {
text: 'Talent',
dataIndex: 'talent',
flex: 1
}],
height: 400,
layout: 'fit',
fullscreen: true
});
}
});

Why the ext component is not overriden although I did exactly as written in documentation?

I would like to override Ext.ux.LiveSearchGridPanel so that instead of text ‘Search’ some other text appears, for example ‘xyz’.
I have a LiveSearchGridPanel as:
Ext.define('MyApp.view.main.List', {
//extend: 'Ext.grid.Panel',
extend: 'Ext.ux.LiveSearchGridPanel',
xtype: 'mainlist',
requires: [
'MyApp.store.Personnel'
],
title: 'Personnel',
store: {
type: 'personnel'
},
columns: [
{ text: 'Name', dataIndex: 'name' },
{ text: 'Email', dataIndex: 'email', flex: 1 },
{ text: 'Phone', dataIndex: 'phone', flex: 1 }
],
listeners: {
select: 'onItemSelected',
afterrender: function() {
console.log('We have been rendered');
}
}
});
I created new file LiveSearchGridPanel123.js in ${app.dir}/overrides directory:
Ext.define('Ext.overrides.LiveSearchGridPanel123', {
override: 'Ext.ux.LiveSearchGridPanel',
initComponent: function () {
var me = this;
console.log(this.self.getName() + ' created 123');
me.tbar = ['XXX', {
xtype: 'textfield',
name: 'searchField',
hideLabel: true,
width: 20,
listeners: {
change: {
fn: me.onTextFieldChange,
scope: this,
buffer: 100
}
}
}, {
xtype: 'button',
text: '<',
tooltip: 'Find Previous Row',
handler: me.onPreviousClick,
scope: me
}, {
xtype: 'button',
text: '>',
tooltip: 'Find Next Row',
handler: me.onNextClick,
scope: me
}
];
me.bbar = Ext.create('Ext.ux.StatusBar', {
defaultText: me.defaultStatusText,
name: 'searchStatusBar'
});
me.callParent(arguments);
}
});
And I added
requires: [
'Ext.overrides.LiveSearchGridPanel123',
],
In app.js.
Then I did sencha app refresh, but component remained the same.
Could you please tell me where the the error is?
screenshot
It's because you call parent this.callParent();.
You can try:
Ext.define(null,{
override:'Ext.ux.LiveSearchGridPanel',
initComponent: function() {
const me = this;
me.tbar = [{
xtype:'textfield'
}];
this.superclass.superclass.initComponent.call(this); //<-- this does the magic
}
});

Form with textfield and grid: send all values to the server

In create and update forms, it is sometimes necessary to give the user the ability to dynamically add fields to values of the same type (more than one phone, more than one address, etc.).
I'm exploring several possibilities to do this.
One of them is to use a grid as a form field.
However, I have doubts about how best to implement this idea, especially on how to send all the form field values (textfield and grid) to the server (and then how to load them later in the form to edit).
Fiddles with some ideas:
One with cellediting plugin https://fiddle.sencha.com/#view/editor&fiddle/2ftp
Another one with roweditin gplugin a https://fiddle.sencha.com/#view/editor&fiddle/2fto
Not sure about the "best to implement", but I have seen so many requirements for multivalue input, that for reusability I have in my toolbox a gridfield similar to the following one:
Ext.define('Ext.ux.GridField', {
extend: 'Ext.form.FieldContainer',
alias: 'widget.gridfield',
initComponent: function () {
var me = this;
if(!me.columns) me.columns = {
dataIndex: 'field1'
};
if(!me.mapFn) me.mapFn = function(value) {
if(Ext.isObject(value)) return value;
return {
field1: value
};
};
if(!me.unmapFn) me.unmapFn = function(record) {
return record.get('field1');
};
me.grid = Ext.widget(Ext.apply({
xtype: 'grid',
viewConfig: {
markDirty: false
},
store: me.store || Ext.create('Ext.data.Store', {
fields: me.columns.map(function(column) {
return {
name: column.dataIndex,
type: column.dataType || 'auto',
defaultValue: column.defaultValue
};
}),
listeners: {
update: me.updateValue,
datachanged: me.updateValue,
scope: me
}
}),
columns: [{
xtype: 'actioncolumn',
getClass: function () {
return 'x-fa fa-times'
},
handler: function(grid, rowIndex, colIndex, item, e, record) {
grid.getStore().remove(record);
},
width: 35
}].concat(me.columns),
bbar: [{
xtype: 'button',
iconCls: 'x-fa fa-pencil',
text: 'Add',
handler: function(btn) {
var grid = btn.up('grid'),
store = grid.getStore(),
record = store.add(Ext.clone(me.emptyRecord) || {})[0];
grid.getPlugin('editor').startEditByPosition({
row: store.indexOf(record),
column: 1
});
}
}],
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
pluginId: 'editor',
clicksToEdit: 1
})
]
}, me.gridConfig)); // "gridConfig" config can override everything on each instance.
me.hiddenField = Ext.widget({
xtype: 'hiddenfield',
name: me.name,
value: '',
allowNull: false,
rawToValue: function (raw) {
return raw;
},
valueToRaw: function (value) {
return value;
},
getRawValue: function () {
return Ext.valueFrom(this.rawValue, '')
},
isEqual: function (a, b) {
return Ext.encode(a) == Ext.encode(b)
},
listeners: {
change: function(field, nV, oV) {
if(!Ext.isArray(nV)) nV = [nV];
var store = me.grid.getStore();
store.removeAll();
store.add(nV.map(me.mapFn));
}
}
});
Ext.apply(me, {
layout: 'fit',
items: [{
xtype:'container',
border: 1,
style: {
borderColor: '#d0d0d0',
borderStyle: 'solid'
},
items: [me.grid]
}, me.hiddenField]
});
me.callParent(arguments);
},
updateValue: function() {
var me = this,
grid = me.grid,
hiddenField = me.hiddenField,
nV = grid.getStore().getRange().map(me.unmapFn, me),
oV = me.hiddenField.getValue();
if(!oV || Ext.isArray(oV) && Ext.encode(nV) != Ext.encode(oV)) {
hiddenField.suspendCheckChange++;
hiddenField.setValue(nV);
hiddenField.suspendCheckChange--;
me.fireEvent('change', me, nV, oV);
}
}
});
which can then be used like this:
},{
xtype: 'gridfield',
fieldLabel: 'Contacts',
name: 'contacts',
columns: [{
text: 'Type',
dataIndex: 'type',
editor:{
xtype: 'combobox',
name: 'type',
valueField: 'name',
displayField: 'name',
store: combostore,
queryMode: 'local'
},
flex: 0.7
},{
text: 'Description',
dataIndex: 'description',
editor:{
xtype: 'textfield',
name: 'description'
},
flex: 1
}],
mapFn: function(value) {
return value;
},
unmapFn: function(record) {
return record.getData();
}
}, {
I have made a fiddle for you based on your fiddle, including working load and save operations on the form, but in ExtJS 6.x. And I have checked that it works with ExtJS 5 as well, although you have to add working icons.

How to display image in column of grid based on value in column's renderer?

I have a grid panel like:
Ext.define('Demo.view.main.content.source.Ex', {
extend: 'Ext.grid.Panel',
requires: [
'Demo.store.main.content.source.Ex',
'Demo.view.main.content.source.ExController',
],
xtype: 'app-main-content-ex',
title: 'Example',
store: 'Demo.store.main.content.source.Ex',
controller:'main-content-source-ex',
//multiSelect: false,
columnLines: true,
initComponent: function() {
var store = Ext.create('Demo.store.main.content.source.Ex', {
storeId: 'app-main-content-source-exstore'
});
Ext.apply(this, {
store: store
});
this.columns= [
{
text : 'Driver Name',
flex : 3,
sortable : false,
dataIndex: 'name'
},
{
xtype: 'gridcolumn',
getEditor: function(record) {
console.log(record.get('state'));
var value;
if (record.get('state') == 'free') {
value = 'xf09c#FontAwesome'
} else {
value = 'xf023#FontAwesome'
}
return Ext.create('Ext.grid.CellEditor', {
field:{
xtype: 'image',
glyph: value
}
});
},
text : 'State',
flex : 1,
dataIndex: 'state'
}]
this.callParent();
},
listeners:{
afterRender: 'setUpInfo'
}
});
I am loading the store of that in grid afterrender event. I want to set the image in the State column based on the value of state(free/busy). Its not working.
How should I do it?
You can use a renderer to augment the displayed value of the cell.
columns: [{
xtype: 'gridcolumn',
dataIndex: 'name',
text: 'Driver Name',
flex: 1,
editor: {
xtype: 'textfield'
}
}, {
xtype: 'gridcolumn',
renderer: function(value) {
if (value == 'free') {
return 'xf09c#FontAwesome'
} else {
return 'xf023#FontAwesome'
}
},
getEditor: function(record) {
var value;
if (record.get('state') == 'free') {
value = 'xf09c#FontAwesome'
} else {
value = 'xf023#FontAwesome'
}
return Ext.create('Ext.grid.CellEditor', {
field: {
xtype: 'image',
glyph: value
}
});
},
text: 'State',
flex: 1,
dataIndex: 'state'
}]
Docs: - http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/#!/api/Ext.grid.column.Column-cfg-renderer

Why is event not fired again when click inside ExtJS 4.2.2 text input field

In the below ExtJS 4.2.2 code, you can click repeatedly on the "Search" and "Show Label" controls, and the label "here is the text" will toggle visible/hidden.
But if you click in the search text input field, the label is only hidden the first time you click there. If you then click "Show Label" to once again display the label, and then again click the search text input field, the label if not hidden.
Ext.define('MyToolbar', {
extend: 'Ext.grid.feature.Feature',
alias: 'feature.myToolbar',
requires: ['Ext.grid.feature.Feature'],
width: 160,
init: function () {
if (this.grid.rendered)
this.onRender();
else{
this.grid.on('render', this.onRender, this);
}
},
onRender: function () {
var panel = this.toolbarContainer || this.grid;
var tb = panel.getDockedItems('toolbar[dock="top"]');
if (tb.length > 0)
tb = tb[0];
else {
tb = Ext.create('Ext.toolbar.Toolbar', {dock: 'top'});
panel.addDocked(tb);
}
this.createSearchBox(tb);
},
createSearchBox: function (tb) {
tb.add({
text: 'Search',
menu: Ext.create('Ext.menu.Menu'),
listeners: {
click: function(comp) {
MyApp.app.fireEvent('onGridToolbarControlClicked', comp);
}
}
});
this.field = Ext.create('Ext.form.field.Trigger', {
width: this.width,
triggerCls: 'x-form-clear-trigger',
onTriggerClick: Ext.bind(this.onTriggerClear, this)
});
this.field.on('render', function (searchField) {
this.field.inputEl.on('click', function() {
MyApp.app.fireEvent('onGridToolbarControlClicked', searchField);
}, this, {single: true});
}, this, {single: true});
tb.add(this.field);
}
});
Ext.define('MyPage', {
extend: 'Ext.container.Container',
alias: 'widget.myPage',
flex: 1,
initComponent: function () {
var me = this;
Ext.applyIf(me, {
items: [{
xtype: 'container',
layout: {
type: 'vbox',
align: 'middle'
},
items: [{
xtype: 'button',
text: 'Show Label',
handler: function(comp) {
comp.up('myPage').down('label').setVisible(true);
}
},{
xtype: 'label',
itemId: 'testLbl',
text: 'here is the text'
},{
xtype: 'gridpanel',
width: 250,
height: 150,
store: Ext.create('Ext.data.Store', {
fields: ['name'],
data: [
{name: 'one'},
{name: 'two'},
{name: 'three'}
]
}),
columns: [{
text: 'Text',
flex: 1,
dataIndex: 'name'
}],
features: [{
ftype: 'myToolbar'
}]
}]
}]
});
me.callParent(arguments);
MyApp.app.on({onGridToolbarControlClicked: function(comp) {
if('function' == typeof comp.up && !Ext.isEmpty(comp.up('myPage')) &&
'function' == typeof comp.up('myPage').down &&
!Ext.isEmpty(comp.up('myPage').down('label'))) {
comp.up('myPage').down('label').setVisible(false);
}
}});
}
});
Ext.onReady(function() {
Ext.application({
name: 'MyApp',
launch: function() {
Ext.create('Ext.container.Viewport', {
renderTo: Ext.getBody(),
width: 700,
height: 500,
layout: 'fit',
items: [{
xtype: 'myPage'
}]
});
}
});
});
Here
this.field.inputEl.on('click', function() {
MyApp.app.fireEvent('onGridToolbarControlClicked', searchField);
}, this, {single: false});
instead of {single:true} in your code. onRender IS single, onClick - (in your case) is not.

Resources