PDA

View Full Version : Grid Search Plugin for Ext 4.x [updated]



Pages : 1 2 3 4 [5]

preichow
7 Aug 2011, 9:38 PM
Ivanblanc, thank you very much for posting a version of the search plugin for 4.0.
When I view my grid, the search box is visible. However, when I enter a search term and hit enter, nothing happens.

I looked at Firebug and discovered that there was an error saying b is undefined. It involves the Extjs-all.js file, line 7, which is here: (function(){var e=this,a=Object.protot...ate("Ext.XTemplate",j,g)}return j}}); (http://www.sencha.com/forum/"{href}")

I have selected the "local" option in my searching.js file, just to keep things simple for now.

the only other strange thing I've noticed is that searching.js file has a line reading "this.grid = this.view.up('gridpanel');". If I change the gridpanel to fit my grid name, it also creates an error saying that it is undefined.

Any ideas from anyone?

Here is an except from my code:


Ext.define('User', { extend: 'Ext.data.Model', fields: ['recordnumber', 'itemprice']});

Ext.define('UsersGrid', {
extend: 'Ext.grid.Panel', initComponent: function() {
var userStore = Ext.create('Ext.data.Store', {
autoLoad: true, model: 'User',
proxy: {
type: 'ajax',
api: {
read: 'extjs/database.php?task=LISTING',
},
reader: { type: 'json', root: 'results', },
},
});
Ext.apply(this, { viewConfig:{ forceFit: false, stripeRows: true, trackOver: true },
store: userStore,
features: [searching],
columns: [{ text: 'Record', width: 45, sortable: true, hideable: true, dataIndex: 'recordnumber' },
{ text: 'Item Price', renderer: 'usMoney', width: 55, sortable: true, hideable: true,
dataIndex: 'itemprice'}],
// paging bar on the bottom
bbar: Ext.create('Ext.PagingToolbar', {
store: userStore,
displayInfo: true,
displayMsg: 'Displaying topics {0} - {1} of {2}',
emptyMsg: "No topics to display",
}),
});
UsersGrid.superclass.initComponent.apply(this,arguments);
}
});

Ext.onReady(function() {
var grid1 = Ext.create('UsersGrid', { renderTo: 'place-for-grid', height: 300, width: 600, title: 'Database' });

ivanleblanc
8 Aug 2011, 6:00 AM
@ preichow

I have put together an example based on to Ext 4 grid examples.
First one being the Basic Array grid to show local searching and the second one is the Infinite Grid example which uses the remote searching.

There is one thing I did change that is not too intuitive because I give no feed back when the error is made. When the actual search is executed if its mode=local then I do nothing special, but if its remote I check to make sure you have a Server proxy configured before I proceed with the search, if you don't then the plugin does nothing.

You will not see the Infinite Grid actually filter because obviously I can't access the back end code of sencha, but you will see the grid load screen come up and the store load request sent with the proper parameters to handle the remote searching.

Should be able to just drop and run this code... just change the path of "Searching.js" to reflect your server.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-4.0.2a/resources/css/ext-all.css">

<script type="text/javascript" src="http://extjs.cachefly.net/ext-4.0.2a/ext-all-debug.js"></script>

<script type="text/javascript" src="/public/ext/ux/4.0/grid/feature/Searching.js"></script>

</head>


<body>


<script type="text/javascript">

Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.state.*',
'Ext.grid.PagingScroller'
]);


Ext.onReady(function() {
Ext.QuickTips.init();

// setup the state provider, all state information will be saved to a cookie
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));


// sample static data for the store
var myData = [
['3m Co', 71.72, 0.02, 0.03, '9/1 12:00am'],
['Alcoa Inc', 29.01, 0.42, 1.47, '9/1 12:00am'],
['Altria Group Inc', 83.81, 0.28, 0.34, '9/1 12:00am'],
['American Express Company', 52.55, 0.01, 0.02, '9/1 12:00am'],
['American International Group, Inc.', 64.13, 0.31, 0.49, '9/1 12:00am'],
['AT&T Inc.', 31.61, -0.48, -1.54, '9/1 12:00am'],
['Boeing Co.', 75.43, 0.53, 0.71, '9/1 12:00am'],
['Caterpillar Inc.', 67.27, 0.92, 1.39, '9/1 12:00am'],
['Citigroup, Inc.', 49.37, 0.02, 0.04, '9/1 12:00am'],
['E.I. du Pont de Nemours and Company', 40.48, 0.51, 1.28, '9/1 12:00am'],
['Exxon Mobil Corp', 68.1, -0.43, -0.64, '9/1 12:00am'],
['General Electric Company', 34.14, -0.08, -0.23, '9/1 12:00am'],
['General Motors Corporation', 30.27, 1.09, 3.74, '9/1 12:00am'],
['Hewlett-Packard Co.', 36.53, -0.03, -0.08, '9/1 12:00am'],
['Honeywell Intl Inc', 38.77, 0.05, 0.13, '9/1 12:00am'],
['Intel Corporation', 19.88, 0.31, 1.58, '9/1 12:00am'],
['International Business Machines', 81.41, 0.44, 0.54, '9/1 12:00am'],
['Johnson & Johnson', 64.72, 0.06, 0.09, '9/1 12:00am'],
['JP Morgan & Chase & Co', 45.73, 0.07, 0.15, '9/1 12:00am'],
['McDonald\'s Corporation', 36.76, 0.86, 2.40, '9/1 12:00am'],
['Merck & Co., Inc.', 40.96, 0.41, 1.01, '9/1 12:00am'],
['Microsoft Corporation', 25.84, 0.14, 0.54, '9/1 12:00am'],
['Pfizer Inc', 27.96, 0.4, 1.45, '9/1 12:00am'],
['The Coca-Cola Company', 45.07, 0.26, 0.58, '9/1 12:00am'],
['The Home Depot, Inc.', 34.64, 0.35, 1.02, '9/1 12:00am'],
['The Procter & Gamble Company', 61.91, 0.01, 0.02, '9/1 12:00am'],
['United Technologies Corporation', 63.26, 0.55, 0.88, '9/1 12:00am'],
['Verizon Communications', 35.57, 0.39, 1.11, '9/1 12:00am'],
['Wal-Mart Stores, Inc.', 45.45, 0.73, 1.63, '9/1 12:00am']
];


/**
* Custom function used for column renderer
* @param {Object} val
*/
function change(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '</span>';
}
return val;
}


/**
* Custom function used for column renderer
* @param {Object} val
*/
function pctChange(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '%</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '%</span>';
}
return val;
}


// create the data store
var store = Ext.create('Ext.data.ArrayStore', {
fields: [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
],
data: myData
});

var searching = {
ftype: 'searching',
mode: 'local'
};


// create the Grid
var grid = Ext.create('Ext.grid.Panel', {
store: store,
features: [searching],
stateful: true,
stateId: 'stateGrid',
columns: [
{
text : 'Company',
flex : 1,
sortable : false,
dataIndex: 'company'
},
{
text : 'Price',
width : 75,
sortable : true,
renderer : 'usMoney',
dataIndex: 'price'
},
{
text : 'Change',
width : 75,
sortable : true,
renderer : change,
dataIndex: 'change'
},
{
text : '% Change',
width : 75,
sortable : true,
renderer : pctChange,
dataIndex: 'pctChange'
},
{
text : 'Last Updated',
width : 85,
sortable : true,
renderer : Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
}
],
height: 350,
width: 600,
title: 'Array Grid',
renderTo: 'basic',
viewConfig: {
stripeRows: true
}
});


//****************************************************************************
// Infinate Grid example
//****************************************************************************
Ext.define('ForumThread', {
extend: 'Ext.data.Model',
fields: [
'title', 'forumtitle', 'forumid', 'author',
{name: 'replycount', type: 'int'},
{name: 'lastpost', mapping: 'lastpost', type: 'date', dateFormat: 'timestamp'},
'lastposter', 'excerpt', 'threadid'
],
idProperty: 'threadid'
});


// create the Data Store
var store = Ext.create('Ext.data.Store', {
id: 'store',
pageSize: 200,
model: 'ForumThread',
remoteSort: true,
// allow the grid to interact with the paging scroller by buffering
buffered: true,
proxy: {
// load using script tags for cross domain, if the data in on the same domain as
// this page, an HttpProxy would be better
type: 'jsonp',
url: 'http://www.sencha.com/forum/remote_topics/index.php',
extraParams: {
total: 50000
},
reader: {
root: 'topics',
totalProperty: 'totalCount'
},
// sends single sort as multi parameter
simpleSortMode: true
},
sorters: [{
property: 'lastpost',
direction: 'DESC'
}]
});


function renderTopic(value, p, record) {
return Ext.String.format(
'<a href="http://sencha.com/forum/showthread.php?t={2}" target="_blank">{0}</a>',
value,
record.data.forumtitle,
record.getId(),
record.data.forumid
);
}


var searching = {
ftype: 'searching',
mode: 'remote',
position: 'top'
};


var grid = Ext.create('Ext.grid.Panel', {
width: 700,
height: 500,
title: 'ExtJS.com - Browse Forums',
store: store,
features: [searching],
verticalScrollerType: 'paginggridscroller',
loadMask: true,
disableSelection: true,
invalidateScrollerOnRefresh: false,
viewConfig: {
trackOver: false
},
// grid columns
columns:[{
xtype: 'rownumberer',
width: 50,
sortable: false
},{
// id assigned so we can apply custom css (e.g. .x-grid-cell-topic b { color:#333 })
// TODO: This poses an issue in subclasses of Grid now because Headers are now Components
// therefore the id will be registered in the ComponentManager and conflict. Need a way to
// add additional CSS classes to the rendered cells.
id: 'topic',
text: "Topic",
dataIndex: 'title',
flex: 1,
renderer: renderTopic,
sortable: false
},{
text: "Author",
dataIndex: 'author',
width: 100,
hidden: true,
sortable: true
},{
text: "Replies",
dataIndex: 'replycount',
align: 'center',
width: 70,
sortable: false
},{
id: 'last',
text: "Last Post",
dataIndex: 'lastpost',
width: 130,
renderer: Ext.util.Format.dateRenderer('n/j/Y g:i A'),
sortable: true
}],
renderTo: Ext.getBody()
});


// trigger the data store load
store.guaranteeRange(0, 199);

});
</script>


<div id="basic"></div>
<br />
<div id="topic-grid"></div>


</body>
</html>

As for the

this.grid = this.view.up('gridpanel');
I had a hard time figuring out where to run the onRender method Saki was using to add the searching toolbar. Other grid features from the API used attachEvents function to initialize stuff for the feature, so that's where I put mine. At that point this.grid was not initiated yet for some reason, but this.view was. So i ran a this.view.up to get me the grid so I could attach the render listener. It is probably kind of funky but it worked so I left it alone.

Patrick86
9 Aug 2011, 2:34 AM
Hi,
Is the plugin works with Ext.ux.maximgb.treegrid.GridPanel ??
ty

venkateshns
16 Aug 2011, 4:51 AM
Saki, this GridSearch plugin has by far been the most useful plugin I have used in Ext 3 and want to thank you for your contribution.

I am moving to Ext 4 and saw that you have not had time yet to port the plugin into Ext 4 so I made a go at it. I hope you don't mind me posting my revisions.

I created a Grid Feature out of the GridSearch plugin.
This feature can easily be applied to the Ext 4 grid example array-grid.js and far as I can tell everything seems to work.

Once the Searching.js file is included you get a ftype "searching".

Searching.js


// JavaScript Document// vim: ts=4:sw=4:nu:fdc=4:nospell
/**
* Search plugin for Ext.grid.GridPanel, Ext.grid.EditorGrid ver. 2.x or subclasses of them
*
* @author Ing. Jozef Sakalos
* @copyright (c) 2008, by Ing. Jozef Sakalos
* @date 17. January 2008
* @version $Id: Ext.ux.grid.Search.js 220 2008-04-29 21:46:51Z jozo $
*
* @license Ext.ux.grid.Search is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/

/*
Revised for Ext 4
by Nathan LeBlanc
on July 8, 2011
*/

Ext.define('Ext.ux.grid.feature.Searching', {
extend: 'Ext.grid.feature.Feature',
alias: 'feature.searching',

/**
* cfg {Boolean} autoFocus true to try to focus the input field on each store load (defaults to undefined)
*/

/**
* @cfg {String} searchText Text to display on menu button
*/
searchText:'Search',

/**
* @cfg {String} searchTipText Text to display as input tooltip. Set to '' for no tooltip
*/
searchTipText:'Type a text to search and press Enter',

/**
* @cfg {String} selectAllText Text to display on menu item that selects all fields
*/
selectAllText:'Select All',

/**
* @cfg {String} position Where to display the search controls. Valid values are top and bottom (defaults to bottom)
* Corresponding toolbar has to exist at least with mimimum configuration tbar:[] for position:top or bbar:[]
* for position bottom. Plugin does NOT create any toolbar.
*/
position:'bottom',

/**
* @cfg {String} iconCls Icon class for menu button (defaults to icon-magnifier)
*/
iconCls:'icon-magnifier',

/**
* @cfg {String/Array} checkIndexes Which indexes to check by default. Can be either 'all' for all indexes
* or array of dataIndex names, e.g. ['persFirstName', 'persLastName']
*/
checkIndexes:'all',

/**
* @cfg {Array} disableIndexes Array of index names to disable (not show in the menu), e.g. ['persTitle', 'persTitle2']
*/
disableIndexes:[],

/**
* @cfg {String} dateFormat how to format date values. If undefined (the default)
* date is formatted as configured in colummn model
*/
dateFormat:undefined,

/**
* @cfg {Boolean} showSelectAll Select All item is shown in menu if true (defaults to true)
*/
showSelectAll:true,

/**
* @cfg {String} menuStyle Valid values are 'checkbox' and 'radio'. If menuStyle is radio
* then only one field can be searched at a time and selectAll is automatically switched off.
*/
menuStyle:'checkbox',

/**
* @cfg {Number} minChars minimum characters to type before the request is made. If undefined (the default)
* the trigger field shows magnifier icon and you need to click it or press enter for search to start. If it
* is defined and greater than 0 then maginfier is not shown and search starts after minChars are typed.
*/

/**
* @cfg {String} minCharsTipText Tooltip to display if minChars is > 0
*/
minCharsTipText:'Type at least {0} characters',

/**
* @cfg {String} mode Use 'remote' for remote stores or 'local' for local stores. If mode is local
* no data requests are sent to server the grid's store is filtered instead (defaults to 'remote')
*/
mode:'remote',

/**
* @cfg {Array} readonlyIndexes Array of index names to disable (show in menu disabled), e.g. ['persTitle', 'persTitle2']
*/

/**
* @cfg {Number} width Width of input field in pixels (defaults to 100)
*/
width:100,

/**
* @cfg {Object} paramNames Params name map (defaults to {fields:'fields', query:'query'}
*/
paramNames: {
fields:'fields'
,query:'query'
},

/**
* @cfg {String} shortcutKey Key to fucus the input field (defaults to r = Sea_r_ch). Empty string disables shortcut
*/
shortcutKey:'r',

/**
* @cfg {String} shortcutModifier Modifier for shortcutKey. Valid values: alt, ctrl, shift (defaults to alt)
*/
shortcutModifier:'alt',

/**
* @cfg {String} align 'left' or 'right' (defaults to 'left')
*/

/**
* @cfg {Number} minLength force user to type this many character before he can make a search
*/

/**
* @cfg {Ext.Panel/String} toolbarContainer Panel (or id of the panel) which contains toolbar we want to render
* search controls to (defaults to this.grid, the grid this plugin is plugged-in into)
*/

attachEvents: function() {
this.grid = this.view.up('gridpanel');
if(this.grid.rendered)
this.onRender();
else
this.grid.on('render', this.onRender, this);
},

onRender:function() {

var panel = this.toolbarContainer || this.grid;
var tb = 'bottom' === this.position ? panel.getDockedItems('toolbar[dock="bottom"]') : panel.getDockedItems('toolbar[dock="top"]');
if(tb.length > 0)
tb = tb[0]
else {
tb = Ext.create('Ext.toolbar.Toolbar', {dock: this.position});
panel.addDocked(tb);
}

// add menu
this.menu = Ext.create('Ext.menu.Menu');

// handle position
if('right' === this.align) {
tb.add('->');
}
else {
if(0 < tb.items.getCount()) {
tb.add('-');
}
}

// add menu button
tb.add({
text:this.searchText
,menu:this.menu
,iconCls:this.iconCls
});

// add input field (TwinTriggerField in fact)
this.field = Ext.create('Ext.form.TwinTriggerField', {
width:this.width,
qtip: 'ddd',
selectOnFocus:undefined === this.selectOnFocus ? true : this.selectOnFocus,
trigger1Cls:'x-form-clear-trigger',
trigger2Cls:this.minChars ? 'x-hidden' : 'x-form-search-trigger',
onTrigger1Click: Ext.bind(this.onTriggerClear, this),
onTrigger2Click: this.minChars ? Ext.emptyFn : Ext.bind(this.onTriggerSearch, this),
minLength:this.minLength
});

// install event handlers on input field
this.field.on('render', function() {

var qtip = this.minChars ? Ext.String.format(this.minCharsTipText, this.minChars) : this.searchTipText;
Ext.QuickTips.register({
target: this.field.inputEl,
text: qtip
});

if(this.minChars) {
this.field.el.on({scope:this, buffer:300, keyup:this.onKeyUp});
}

// install key map
var map = new Ext.KeyMap(this.field.el, [{
key:Ext.EventObject.ENTER
,scope:this
,fn:this.onTriggerSearch
},{
key:Ext.EventObject.ESC
,scope:this
,fn:this.onTriggerClear
}]);
map.stopEvent = true;
}, this, {single:true});

tb.add(this.field);

// reconfigure
this.reconfigure();

// keyMap
if(this.shortcutKey && this.shortcutModifier) {
var shortcutEl = this.grid.getEl();
var shortcutCfg = [{
key:this.shortcutKey
,scope:this
,stopEvent:true
,fn:function() {
this.field.focus();
}
}];
shortcutCfg[0][this.shortcutModifier] = true;
this.keymap = new Ext.KeyMap(shortcutEl, shortcutCfg);
}

if(true === this.autoFocus) {
this.grid.store.on({scope:this, load:function(){this.field.focus();}});
}
} // eo function onRender
// }}}
// {{{
/**
* field el keypup event handler. Triggers the search
* @private
*/
,onKeyUp:function() {
var length = this.field.getValue().toString().length;
if(0 === length || this.minChars <= length) {
this.onTriggerSearch();
}
} // eo function onKeyUp
// }}}
// {{{
/**
* private Clear Trigger click handler
*/
,onTriggerClear:function() {
if(this.field.getValue()) {
this.field.setValue('');
this.field.focus();
this.onTriggerSearch();
}
} // eo function onTriggerClear
// }}}
// {{{
/**
* private Search Trigger click handler (executes the search, local or remote)
*/
,onTriggerSearch:function() {
if(!this.field.isValid()) {
return;
}
var val = this.field.getValue(),
store = this.grid.store,
proxy = store.getProxy();

// grid's store filter
if('local' === this.mode) {
store.clearFilter();
if(val) {
store.filterBy(function(r) {
var retval = false;
this.menu.items.each(function(item) {
if(!item.checked || retval) {
return;
}
var rv = r.get(item.dataIndex);
rv = rv instanceof Date ? Ext.Date.format(rv, this.dateFormat || r.fields.get(item.dataIndex).dateFormat) : rv;
var re = new RegExp(val, 'gi');
retval = re.test(rv);
}, this);
if(retval) {
return true;
}
return retval;
}, this);
}
else {
}
}
// ask server to filter records
// your proxy must be a Server proxy
else if(proxy instanceof Ext.data.proxy.Server) {
// clear start (necessary if we have paging)
if(store.lastOptions && store.lastOptions.params) {
store.lastOptions.params[store.paramNames.start] = 0;
}

// get fields to search array
var fields = [];
this.menu.items.each(function(item) {
if(item.checked && item.dataIndex) {
fields.push(item.dataIndex);
}
});

// add fields and query to baseParams of store
delete(proxy.extraParams[this.paramNames.fields]);
delete(proxy.extraParams[this.paramNames.query]);
if (store.lastOptions && store.lastOptions.params) {
delete(proxy.lastOptions.params[this.paramNames.fields]);
delete(proxy.lastOptions.params[this.paramNames.query]);
}
if(fields.length) {
proxy.extraParams[this.paramNames.fields] = Ext.encode(fields);
proxy.extraParams[this.paramNames.query] = val;
}

// reload store
store.load();
}

} // eo function onTriggerSearch
// }}}
// {{{
/**
* @param {Boolean} true to disable search (TwinTriggerField), false to enable
*/
,setDisabled:function() {
this.field.setDisabled.apply(this.field, arguments);
} // eo function setDisabled
// }}}
// {{{
/**
* Enable search (TwinTriggerField)
*/
,enable:function() {
this.setDisabled(false);
} // eo function enable
// }}}
// {{{
/**
* Enable search (TwinTriggerField)
*/
,disable:function() {
this.setDisabled(true);
} // eo function disable
// }}}
// {{{
/**
* private (re)configures the plugin, creates menu items from column model
*/
,reconfigure:function() {

// {{{
// remove old items
var menu = this.menu;
menu.removeAll();

// add Select All item plus separator
if(this.showSelectAll && 'radio' !== this.menuStyle) {
menu.add({
xtype: 'menucheckitem',
text:this.selectAllText,
checked:!(this.checkIndexes instanceof Array),
hideOnClick:false,
handler:function(item) {
var checked = item.checked;
item.parentMenu.items.each(function(i) {
if(item !== i && i.setChecked && !i.disabled) {
i.setChecked(checked);
}
});
}
},'-');
}

// }}}
// {{{
// add new items
var columns = this.grid.headerCt.items.items;
var group = undefined;
if('radio' === this.menuStyle) {
group = 'g' + (new Date).getTime();
}

Ext.each(columns, function(column) {
var disable = false;
if(column.text && column.dataIndex && column.dataIndex != '') {
Ext.each(this.disableIndexes, function(item) {
disable = disable ? disable : item === column.dataIndex;
});
if(!disable) {
menu.add({
xtype: 'menucheckitem',
text: column.text,
hideOnClick: false,
group:group,
checked: 'all' === this.checkIndexes,
dataIndex: column.dataIndex,
});
}
}
}, this);
// }}}
// {{{
// check items
if(this.checkIndexes instanceof Array) {
Ext.each(this.checkIndexes, function(di) {
var item = menu.items.find(function(itm) {
return itm.dataIndex === di;
});
if(item) {
item.setChecked(true, true);
}
}, this);
}
// }}}
// {{{
// disable items
if(this.readonlyIndexes instanceof Array) {
Ext.each(this.readonlyIndexes, function(di) {
var item = menu.items.find(function(itm) {
return itm.dataIndex === di;
});
if(item) {
item.disable();
}
}, this);
}
// }}}

} // eo function reconfigure
// }}}

}); // eo extend

// eof




var searching = {
ftype: 'searching',
minChars: 2,
mode: 'local'
};


Then in your Grid config (this comes straight from array-grid.js in the examples):


var grid = Ext.create('Ext.grid.Panel', {
store: store,
stateful: true,
stateId: 'stateGrid',
features: [searching],
columns: [
{
text : 'Company',
flex : 1,
sortable : false,
dataIndex: 'company'
}
....


I have done the same thing but i am getting the following error. Can u please help me out.

features[i] is undefined

if (!features[i].isFeature) {

in the firefox console.


Regards,
Venkatesh

nebbian
3 Sep 2011, 2:36 AM
Hi ivanleblanc,

Thank you so much for porting this excellent plugin to Ext4.

It works perfectly for me, straight out of the box :D

I particularly like the way it will search after a short delay, without having to hit "Enter". I'm not sure if the original plugin was able to be configured to do this, but it was always necessary for me to hit "Enter" before the new data would show up. Btw I'm using remote stores.

This is awesome, thanks again B)

panpur
11 Sep 2011, 1:01 AM
Thanks Saki & ivanleblanc, this is wonderful. I think I found a bug though.

If I have tabpanel with 2 tabs, each tab contains a searchable grid. Then first grid will not have the search box, while the second grid will have 2 search boxes.

I'm attaching a screenshot.
27994

Hope this will be fixed soon :D
Thanks!

mvsrekha
20 Apr 2012, 5:55 AM
Can you please tell from the scratch, how to use this Grid Search Plugin using Asp.Net MVC.
i was able to load gridpanel successfully with paging and sorting features..but i need search feature also in my gridpanel.

i have googled a lot for solution. but i got nothing...can you please help me out ...



Hi all,

the self-contained Grid Search Plugin usage example follows. This example is configured to use local filtering (mode:'local') but remote mode, when serching itself is done by the server, is also possible. The plugin should also work with AutoGrid(s) and paging grids.

Enjoy.


http://gridsearch.extjs.eu

ivanleblanc
23 Apr 2012, 5:42 AM
@ panpur
Can you post some code, may be how you have it laid out or something.
Here's a quick example I made using the grid-array.js example form docs and it seems to work fine.

I am using the Ext 4.1 rc3 in this example...


<html>
<head>
<title>Grid Search</title>

<link rel="stylesheet" type="text/css" href="../../../public/ext/4.1.0-rc3/resources/css/ext-all.css">

<script type="text/javascript" src="../../../public/ext/4.1.0-rc3/ext-all-debug.js"></script>

<script type="text/javascript" src="../../../public/ext/ux/4.1/grid/feature/Searching.js"></script>




<script type="text/javascript">




Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.state.*'
]);


Ext.define('Company', {
extend: 'Ext.data.Model',
fields: [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
],
idProperty: 'company'
});


Ext.onReady(function() {
Ext.QuickTips.init();

// setup the state provider, all state information will be saved to a cookie
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));


// sample static data for the store
var myData = [
['3m Co', 71.72, 0.02, 0.03, '9/1 12:00am'],
['Alcoa Inc', 29.01, 0.42, 1.47, '9/1 12:00am'],
['Altria Group Inc', 83.81, 0.28, 0.34, '9/1 12:00am'],
['American Express Company', 52.55, 0.01, 0.02, '9/1 12:00am'],
['American International Group, Inc.', 64.13, 0.31, 0.49, '9/1 12:00am'],
['AT&T Inc.', 31.61, -0.48, -1.54, '9/1 12:00am'],
['Boeing Co.', 75.43, 0.53, 0.71, '9/1 12:00am'],
['Caterpillar Inc.', 67.27, 0.92, 1.39, '9/1 12:00am'],
['Citigroup, Inc.', 49.37, 0.02, 0.04, '9/1 12:00am'],
['E.I. du Pont de Nemours and Company', 40.48, 0.51, 1.28, '9/1 12:00am'],
['Exxon Mobil Corp', 68.1, -0.43, -0.64, '9/1 12:00am'],
['General Electric Company', 34.14, -0.08, -0.23, '9/1 12:00am'],
['General Motors Corporation', 30.27, 1.09, 3.74, '9/1 12:00am'],
['Hewlett-Packard Co.', 36.53, -0.03, -0.08, '9/1 12:00am'],
['Honeywell Intl Inc', 38.77, 0.05, 0.13, '9/1 12:00am'],
['Intel Corporation', 19.88, 0.31, 1.58, '9/1 12:00am'],
['International Business Machines', 81.41, 0.44, 0.54, '9/1 12:00am'],
['Johnson & Johnson', 64.72, 0.06, 0.09, '9/1 12:00am'],
['JP Morgan & Chase & Co', 45.73, 0.07, 0.15, '9/1 12:00am'],
['McDonald\'s Corporation', 36.76, 0.86, 2.40, '9/1 12:00am'],
['Merck & Co., Inc.', 40.96, 0.41, 1.01, '9/1 12:00am'],
['Microsoft Corporation', 25.84, 0.14, 0.54, '9/1 12:00am'],
['Pfizer Inc', 27.96, 0.4, 1.45, '9/1 12:00am'],
['The Coca-Cola Company', 45.07, 0.26, 0.58, '9/1 12:00am'],
['The Home Depot, Inc.', 34.64, 0.35, 1.02, '9/1 12:00am'],
['The Procter & Gamble Company', 61.91, 0.01, 0.02, '9/1 12:00am'],
['United Technologies Corporation', 63.26, 0.55, 0.88, '9/1 12:00am'],
['Verizon Communications', 35.57, 0.39, 1.11, '9/1 12:00am'],
['Wal-Mart Stores, Inc.', 45.45, 0.73, 1.63, '9/1 12:00am']
];


/**
* Custom function used for column renderer
* @param {Object} val
*/
function change(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '</span>';
}
return val;
}


/**
* Custom function used for column renderer
* @param {Object} val
*/
function pctChange(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '%</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '%</span>';
}
return val;
}


// create the data store
var store1 = Ext.create('Ext.data.ArrayStore', {
model: 'Company',
data: myData
});


var store2 = Ext.create('Ext.data.ArrayStore', {
model: 'Company',
data: myData
});

// create Grid Searching feature
var searching = {
ftype: 'searching',
minChars: 2,
position: 'top',
mode: 'local'
};


// create the Grid
var grid1 = Ext.create('Ext.grid.Panel', {
store: store1,
stateful: true,
collapsible: true,
multiSelect: true,
stateId: 'stateGrid',
features: [searching],
columns: [
{
text : 'Company',
flex : 1,
sortable : false,
dataIndex: 'company'
},
{
text : 'Price',
width : 75,
sortable : true,
renderer : 'usMoney',
dataIndex: 'price'
},
{
text : 'Change',
width : 75,
sortable : true,
renderer : change,
dataIndex: 'change'
},
{
text : '% Change',
width : 75,
sortable : true,
renderer : pctChange,
dataIndex: 'pctChange'
},
{
text : 'Last Updated',
width : 85,
sortable : true,
renderer : Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
}
],
height: 350,
width: 600,
title: 'Array Grid',
//renderTo: Ext.getBody(),
viewConfig: {
stripeRows: true,
enableTextSelection: true
}
});


var grid2 = Ext.create('Ext.grid.Panel', {
store: store2,
stateful: true,
collapsible: true,
multiSelect: true,
stateId: 'stateGrid',
tbar: ['->'],
features: [searching],
columns: [
{
text : 'Company',
flex : 1,
sortable : false,
dataIndex: 'company'
},
{
text : 'Price',
width : 75,
sortable : true,
renderer : 'usMoney',
dataIndex: 'price'
},
{
text : 'Change',
width : 75,
sortable : true,
renderer : change,
dataIndex: 'change'
},
{
text : '% Change',
width : 75,
sortable : true,
renderer : pctChange,
dataIndex: 'pctChange'
},
{
text : 'Last Updated',
width : 85,
sortable : true,
renderer : Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
}
],
height: 350,
width: 600,
title: 'Array Grid',
//renderTo: Ext.getBody(),
viewConfig: {
stripeRows: true,
enableTextSelection: true
}
});

var tabpanel = Ext.create('Ext.tab.Panel', {
renderTo: Ext.getBody(),
items: [
grid1,
grid2
]
});
});




</script>
</head>


<body>


</body>
</html>

mvsrekha
23 Apr 2012, 7:04 AM
Can you please tell me how to implement the above grid search dynamically using asp.net MVC 3.
Grid should have sorting, paging and searching features.

Thanks in advance

ivanleblanc
23 Apr 2012, 8:04 AM
Can you please tell me how to implement the above grid search dynamically using asp.net MVC 3.
Grid should have sorting, paging and searching features.

Thanks in advance

I unfortunately have no experience in asp.net MVC 3.
I am sorry.

panpur
23 Apr 2012, 7:21 PM
@ivanleblanc
Sorry, it was a stupid mistake. I put the feature config in custom grid's parent class.

I should have updated my post, but I was caught up in super ultra urgent project back then. My sincere apologies for wasting your time.

Thanks

codeart.ch
9 May 2012, 4:39 AM
Ext.each(columns, function(column) {
var disable = false;
if(column.text && column.dataIndex && column.dataIndex != '') {
Ext.each(this.disableIndexes, function(item) {
disable = disable ? disable : item === column.dataIndex;
});
if(!disable) {
if(typeof column.searchable != 'undefined' && column.searchable == false) {
disable = true;
}
}
if(!disable) {
menu.add({
xtype: 'menucheckitem',
text: column.text,
hideOnClick: false,
group:group,
checked: 'all' === this.checkIndexes,
dataIndex: column.dataIndex,
});
}
}
}, this);


I added a functionality for a column based searchable configuration.

This can be used like


this.columns = [{
text:'ID',
dataIndex:'id',
width:50,
searchable:false
},{.....

codeart.ch
9 May 2012, 6:17 AM
Bugfix for datecolumns with the format property like:



,{
text:'date',
dataIndex:'datecreated',
xtype:'datecolumn',
format:'d.m.Y H:i'
}




// grid's store filter
if('local' === this.mode) {
store.clearFilter();
if(val) {
store.filterBy(function(r) {
var retval = false;
this.menu.items.each(function(item) {
if(!item.checked || retval) {
return;
}
var rv = r.get(item.dataIndex);
var cformat = this.grid.columns[Ext.Array.indexOf(Ext.Array.pluck(this.grid.columns, 'dataIndex'), item.dataIndex)].format;

rv = rv instanceof Date ? Ext.Date.format(rv, this.dateFormat || cformat) : rv;
var re = new RegExp(val, 'gi');
retval = re.test(rv);
}, this);
if(retval) {
return true;
}
return retval;
}, this);
}
else {
}
}


The error before was the follow 'format is null' because the format or dateFormat was null in the field (the error only occured in local mode):

35032

bareflix
30 May 2012, 3:56 PM
Does Ivanblanc's 4.0 port work with 4.1? Or is there a 4.1 native alternative?
This is such a great feature, I keep hoping they will make it part of the toolkit.

panpur
30 May 2012, 4:12 PM
Does Ivanblanc's 4.0 port work with 4.1? Or is there a 4.1 native alternative?
This is such a great feature, I keep hoping they will make it part of the toolkit.

Yes it is, I use it on my project with ExtJS 4.1

aislan
16 Jul 2012, 10:33 AM
I can use this port to a grid with data from the server?


Just get it to work with grid-array. :(

vicvolk
21 Aug 2012, 8:53 AM
Hi, guys. Who knows how to make this plugin work with a grid having grouped headers like header 1 -- header 1.1 header 1.2. Now it is possible to search over "simple" headers. Grouped headers are ignored.

38126

vicvolk
22 Aug 2012, 10:39 PM
Hi, guys. Who knows how to make this plugin work with a grid having grouped headers like header 1 -- header 1.1 header 1.2. Now it is possible to search over "simple" headers. Grouped headers are ignored.

38126

I made it work for me. Instead of



Ext.each(columns, function(column) {
var disable = false;
if(column.text && column.dataIndex && column.dataIndex != '') {
Ext.each(this.disableIndexes, function(item) {
disable = disable ? disable : item === column.dataIndex;
});
if(!disable) {
menu.add({
xtype: 'menucheckitem',
text: column.text,
hideOnClick: false,
group:group,
checked: 'all' === this.checkIndexes,
dataIndex: column.dataIndex,
});
}

}
}, this);


I simply wrote this piece of code



var cls = this.grid.headerCt.getGridColumns();

var i = 0;

while(i < cls.length){

//i == 0 is my first check column

if(this.grid.headerCt.getHeaderAtIndex(i) && i != 0) {

menu.add({
xtype: 'menucheckitem',
text: this.grid.headerCt.getHeaderAtIndex(i).text,
hideOnClick: false,
group:group,
checked: 'all' === this.checkIndexes,
dataIndex: this.grid.headerCt.getHeaderAtIndex(i).dataIndex,
});

}

i++;

}


Now it iterates trough all columns.

hieu79vn
13 Sep 2012, 4:13 AM
Hello

I did as your instruction to plugin the grid search function, but it raise an error
Uncaught TypeError: Object #<Object> has no method 'reg' Ext.ux.grid.RowActions.js:423 (http://localhost/buyer_technip/extjs/Ext.ux.grid.RowActions.js)
Uncaught TypeError: Object function (parentNode, containerIdx) {
} has no method 'createSequence' Ext.ux.grid.Search.js:169 (http://localhost/buyer_technip/extjs/Ext.ux.grid.Search.js)

What is the problem?

Thank you

buhari
1 Feb 2013, 3:33 AM
Pls am new to Ext js. I will like to be directed on how to use it.

vicvolk
24 Feb 2013, 12:05 AM
In extjs 4.1.1 this plug-in unfortunately causes some terrible mess-up.

vicvolk
24 Feb 2013, 12:23 AM
This mess-up happens because of some conflict with Ext.tip.QuickTipManager. Inside the definition of register function:

register:function(){b.register.apply(b,arguments)}

I had to check whether b is defined, so now it is

register:function(){if(b!==undefined)b.register.apply(b,arguments)}

And now it works perfectly.

unnamed_dev
6 May 2013, 2:14 PM
little mod for 4.2x

attachEvent now unavalible



init: function(grid) {
var me = this,
view = me.view;


me.callParent(arguments);
grid.on({
afterrender: function() {
me.onRender();
},
single: true
});
},


code really dirty ;)

extjsquicklearner
7 May 2013, 2:40 PM
WIll this work with extjs 2.3 ?
how should i add it to the existing one ?

berend
11 Aug 2013, 5:15 PM
To avoid having to huntdown the latest ExtJS 4.2 patches, I've put it all on github: https://github.com/berenddeboer/Ext.ux.grid.feature.Searching

jacinth_1215
4 Nov 2013, 5:16 PM
Hi Guys,

I'm having a problem with the mode local or remote..

Actually if I use local it would return values based on the values I enter like
when I type 'a' all values that start with 'a' returns but

if I use remote it needs 4 characters to return since I'm using a query 'SELECT LIKE '%%' ' ...
Can anyone help me that the remote would return values even I just enter one character..???

ivanleblanc
5 Nov 2013, 6:25 AM
Hi Guys,

I'm having a problem with the mode local or remote..

Actually if I use local it would return values based on the values I enter like
when I type 'a' all values that start with 'a' returns but

if I use remote it needs 4 characters to return since I'm using a query 'SELECT LIKE '%%' ' ...
Can anyone help me that the remote would return values even I just enter one character..???

I don't quite understand what your saying.
you said "If I use remote it needs 4 characters" how many characters it needs is a config setting:
minChars
are you setting that? If you set

minChars: 1
then when the search textfield reaches 1 char then the search will be fired.

jacinth_1215
5 Nov 2013, 6:00 PM
I don't quite understand what your saying.
you said "If I use remote it needs 4 characters" how many characters it needs is a config setting:
minChars
are you setting that? If you set

minChars: 1
then when the search textfield reaches 1 char then the search will be fired.

Hello ivanleblanc,

What actually searching for is right exactly what you understand. Thanks so much and sorry for my bad English. :D

shankar8rajah1
14 Nov 2013, 9:13 AM
Hi,

I am using this plugin which works great! I was wondering, I put this on a toolbar, but the x is not going all the way to the end. I used Firebug and noticed a small empty box at the end (it used to be white, I changed the color to blue). How can I get rid of this so that the search is aligned properly?

46839

ivanleblanc
14 Nov 2013, 12:03 PM
Hi,

I am using this plugin which works great! I was wondering, I put this on a toolbar, but the x is not going all the way to the end. I used Firebug and noticed a small empty box at the end (it used to be white, I changed the color to blue). How can I get rid of this so that the search is aligned properly?

46839
Whether the second image is there or not is determined by the minChars config setting.
If you dont have a minChars then the Search icon appears and it looks fine.
If you do have a minChars set then the second icon should disappear.
Heres that code copied from Searching.js


// add input field (TwinTriggerField in fact)
this.field = Ext.create('Ext.form.TwinTriggerField', {
width: this.width,
qtip: 'ddd',
selectOnFocus: undefined === this.selectOnFocus ? true : this.selectOnFocus,
trigger1Cls: 'x-form-clear-trigger',
trigger2Cls: this.minChars ? 'x-hidden' : 'x-form-search-trigger',
onTrigger1Click: Ext.bind(this.onTriggerClear, this),
onTrigger2Click: this.minChars ? Ext.emptyFn : Ext.bind(this.onTriggerSearch, this),
minLength: this.minLength
});


When inspecting the empty image in the browser you can see that 'x-hidden' is applied to hide the image but the TD is still there. I'm thinking this must be a Ext version issue. They must have changed the layout of the Triggers on this TriggerField. If I come up with a solution I'll post it.
Unfortunately I rarely use this grid feature with a minChars set, so never really noticed it was doing that.

King_Aero
29 Nov 2013, 7:48 AM
Whether the second image is there or not is determined by the minChars config setting.
If you dont have a minChars then the Search icon appears and it looks fine.
If you do have a minChars set then the second icon should disappear.
Heres that code copied from Searching.js


// add input field (TwinTriggerField in fact)
this.field = Ext.create('Ext.form.TwinTriggerField', {
width: this.width,
qtip: 'ddd',
selectOnFocus: undefined === this.selectOnFocus ? true : this.selectOnFocus,
trigger1Cls: 'x-form-clear-trigger',
trigger2Cls: this.minChars ? 'x-hidden' : 'x-form-search-trigger',
onTrigger1Click: Ext.bind(this.onTriggerClear, this),
onTrigger2Click: this.minChars ? Ext.emptyFn : Ext.bind(this.onTriggerSearch, this),
minLength: this.minLength
});


When inspecting the empty image in the browser you can see that 'x-hidden' is applied to hide the image but the TD is still there. I'm thinking this must be a Ext version issue. They must have changed the layout of the Triggers on this TriggerField. If I come up with a solution I'll post it.
Unfortunately I rarely use this grid feature with a minChars set, so never really noticed it was doing that.

I found the following will work to solve this issue with minChars:



// add input field (TwinTriggerField in fact)
this.field = Ext.create('Ext.form.field.Trigger', {
cls: "grid-search",
width: this.width,
qtip: 'ddd',
selectOnFocus: undefined === this.selectOnFocus ? true : this.selectOnFocus,
triggerCls:'x-form-clear-trigger',
onTriggerClick: Ext.bind(this.onTriggerClear, this),
minLength:this.minLength
});

if (!this.minChars) {
Ext.apply(this.field, {
trigger2Cls:'x-form-search-trigger',
onTrigger2Click: Ext.bind(this.onTriggerSearch, this),
});
}

bwgv
26 Mar 2014, 8:25 AM
hi, does anybody knows to implement this plug in in SA3 ? thx a lot

venkikodakirthi
28 Mar 2014, 6:41 AM
I am using this plug in to search the grid. My grid has locked columns. But search is ignoring the locked columns. When I debugged onRender() method is called twice. Once for just the locked columns and once for the rest of the column. Leaving only non locked columns for searching. Since we are calling the reconfigure() twice for the grid, locked columns got removed when this method is called 2nd time. // {{{ // remove old items var menu = this.menu; menu.removeAll();Any solutions?

jsakalos
11 May 2014, 9:51 AM
UPDATED!

See the first post (http://www.sencha.com/forum/showthread.php?23615-Grid-Search-Plugin&p=111752&viewfull=1#post111752).