PDA

View Full Version : Updating multiple grids with one store.load()



Vaevictus
30 Jun 2009, 4:11 AM
Hi,

Apologies but this is the second time I have typed this out as the forum lost the first one :((

Basically I want to load a grid via an xmlreader.
on grid load, update another grid, reusing the same XMLdocument received from the server.
(one grid uses one list of nodes from the xml, the other grid uses another)

Here is the main grids code:

/*
* Ext JS Library 2.1
* Copyright(c) 2006-2008, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/
/// <reference path="vswd-ext_2.1.js" />

ResultsGrid = function() {


this.expander = new Ext.grid.RowExpander({
tpl: new Ext.Template(
'<p style="margin:0 0 4px 8px">{description}</p>'

)
});
this.action = new Ext.ux.grid.RowActions({
header: 'Actions'
// ,autoWidth:false
, actions: [{
//iconIndex: 'preview-action'
// qtipIndex: 'qtip1'
iconCls: 'icon-magnifier'
, tooltip: 'Preview Document'

}, {
iconCls: 'icon-similar'
, tooltip: 'Similar Documents'

}, {
iconCls: 'icon-email-link'
, tooltip: 'Email this document to a colleague'

},
{
iconCls: 'icon-chart'
, tooltip: 'Statistics'

}, {
//scrapbook: only available to some users
tooltip: 'Add to scrapbook',
iconIndex: 'scrapbook'
//, hideIndex: 'hide2'
// ,text:'Open'
}]
, callbacks: {

'icon-magnifier': function(grid, record, action, row, col) {
// alert('preview:' + record.data.title);
showPreview(550, 550, record.data.previewlink, grid.store.lastOptions.params.Text)
},
'icon-similar': function(grid, record, action, row, col) {
showSimilar(550, 550, record.data.id);
},

'icon-email-link': function(grid, record, action, row, col) {
alert('preview:' + record.data.title);
},
'icon-chart': function(grid, record, action, row, col) {
showGraph(590, 515, record.data.untoucheddate, grid.store.lastOptions.params.Text)
}
}
});

// this.hotIcons = new Ext.ux.grid.RowActions({
// header: 'Tags'
// // ,autoWidth:false
// , actions: [{
// iconIndex: 'tag1'
// // qtipIndex: 'qtip1'
// //iconCls: 'icon-magnifier'
// //, tooltip: 'Preview Document'

// }, {
// iconIndex: 'tag2'
//

// }, {
// iconIndex: 'tag3'
// }]
// , callbacks: {

// //no callbacks, icon clicks do nothing for hoticons
//
// }
// });


this.store = new Ext.data.GroupingStore({
//groupField: 'foldername',
remoteSort: true,
proxy: new Ext.data.HttpProxy({
// url: 'SimpleQuery.asmx/Query', method: 'GET'
url: 'Query.aspx', method: 'GET'
}),
baseParams: { start: 0, limit: 20 },

reader: new Ext.data.XmlReader(
{ record: 'hit', totalRecords: 'totalhits' },
[{ name: 'title', mapping: 'title' },
{ name: 'foldername', mapping: 'content/DOCUMENT/FOLDERNAME' },
'database',
//dates
{name: 'untoucheddate', type: 'string', mapping: 'content/DOCUMENT/DREDATE' },
{ name: 'hoticons', type: 'string', mapping: 'thehotcats' },
{ name: 'pubDate', type: 'date', dateFormat: 'U', mapping: 'content/DOCUMENT/DREDATE' },
//end dates
{name: 'description', mapping: 'summary', type: 'string' },
{ name: 'content', mapping: 'summary', type: 'string' },
{ name: 'link', mapping: 'viewreference' },
{ name: 'previewlink', mapping: 'previewreference' },
{ name: 'weight', mapping: 'weight', type: 'string' },
{ name: 'id', type: 'string'}]
)
});
this.view = new Ext.grid.GroupingView({

forceFit: true,
forceFit: true,
enableRowBody: true,
showPreview: true,
getRowClass: this.applyRowClass,
groupTextTpl: '{text} ({[values.rs.length]})'
});

this.store.setDefaultSort('pubDate', "DESC"); //this should be set by prefs TODO craig
this.bbar = new Ext.PagingToolbar({
//pageSize: prefs.numResults,
pageSize: 20,
store: this.store,
// displayInfo: true,
// displayMsg: 'Displaying documents {0} - {1} of {2}',
// emptyMsg: "No results to display",
plugins: [new Ext.ux.grid.PageSizer(),
new Ext.ux.grid.AutoRefresher()]

//bbar items were here

});

// Ext.apply(this, config);


this.columns = [this.expander,
{
header: "Title",
dataIndex: 'title',
sortable: true,
width: 375,
renderer: this.formatTitle
}, {
header: "Tags",
dataIndex: 'hoticons',
sortable: false,
width: 90,
renderer: this.formatIcons
},
{
header: "Source",
dataIndex: 'database',
width: 75,
hidden: true,
sortable: true
//renderer: this.formatAuthor //TODO maybe
}, {
header: "SubFolder",
dataIndex: 'foldername',
width: 75,
hidden: true,
sortable: true
// renderer: this.formatAuthor //TODO maybe
}, {
header: "Date",
dataIndex: 'pubDate',
width: 90,
renderer: this.formatDate,
sortable: true
}, this.action];

ResultsGrid.superclass.constructor.call(this, {
stateful: false, //craig dont know if this works, columns widths seem to have memory
region: 'center',
renderTo: 'divGrid', //untested
id: 'results-grid',
loadMask: { msg: 'Loading AOSS Data...' },
sortInfo: { field: 'source', direction: "ASC" }, //from prefs maybe - TODO
height: 700,
width: 820,
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
}),
plugins: [this.action, this.expander], //important
view: this.view,
viewConfig: {
forceFit: true,
enableRowBody: true,
showPreview: true,
getRowClass: this.applyRowClass
}
});

this.on('rowcontextmenu', this.onContextClick, this);

//this event fires when the main grid's data is loaded (ie a new search has been performed). We use this event to update the suggestions grid, if there is one);
this.store.proxy.on('load', this.updateSuggestions, this);

};

Ext.extend(ResultsGrid, Ext.grid.GridPanel, {

updateSuggestions: function(callingProxy, xmldoc, callingProxyArgs) {

//try and find a suggestions gridpanel
var suggestionsGrid = Ext.getCmp('suggestions-grid');
if (suggestionsGrid == null) { return; }

//we have the grid, we now pass it a copy of the XML data we have just received from the server, we get back a datablock that can be passed to the store
var datablock = suggestionsGrid.store.reader.read(callingProxy.conn.response);

//pass this datablock to the suggestionsgrid store
suggestionsGrid.store.loadData(datablock);
suggestionsGrid.view.refresh();
//finished!
},
Search: function(searchParams) {

//anything with value = 'on' means radio is ticked //TODO hardcoding = bad
//searchParams.sources = '';
// for (var i = 0, len = searchParams.sourcesList.length; i < len; i++) {

// searchParams.sources += searchParams.sourcesList[i].sourceId;
// searchParams.sources += ',';
// }


// if (searchParams.catId == '') { searchParams.catId = 'All'; }
// if (searchParams.sources == '') {

// toastAlert('No sources were selected ', 'Error');
// return;
// }

// this.store.load({ params: { start: 0, limit: 200, strQuery: searchParams.strQuery, summary: 'Concept', catId: searchParams.catId, sources: mysources, nowords: '',atleast: '', startDate: searchParams.startDate, endDate: searchParams.endDate, exactphrase: searchParams.exactphrase} }); //CRAIG ADDED PARAMS TO CONTROL MAX AMOUNT OF ITEMS TO LOAD
this.store.baseParams = searchParams;
this.store.load({ params: { start: 0, limit: 20} });

if (!searchParams['saveAsText']) { searchParams['saveAsText'] = searchParams['strQuery']; }
// Ext.getCmp('queries-tree').addRecent(searchParams, true);
},

onContextClick: function(grid, index, e) {
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'grid-ctx',
items: [{
text: 'View in new tab',
iconCls: 'new-tab',
scope: this,
handler: function() {
this.viewer.openTab(this.ctxRecord);
}
}, {
iconCls: 'new-win',
text: 'Go to Post',
scope: this,
handler: function() {
window.open(this.ctxRecord.data.link);
}
}, '-', {
iconCls: 'refresh-icon',
text: 'Refresh Search',
scope: this,
handler: function() {
this.ctxRow = null;
this.store.reload();
}
},
{
iconCls: 'savesearch-icon', //TODO
text: 'Save news item to favourites',
scope: this,
handler: function() {
this.ctxRow = null;
if (!this.saveStoryWin) {
this.saveStoryWin = new saveStoryWin();
}
this.menu.hide();
this.saveStoryWin.reference = this.ctxRecord.data.link;
this.saveStoryWin.show(this.ctxRecord.data.title, this.ctxRecord.data.link);
}
}


,
{
iconCls: 'savesearch-icon', //TODO
text: 'Save query to favourites',
scope: this,
handler: function() {
this.ctxRow = null;
if (!this.saveQueryWin) {
this.saveQueryWin = new saveQueryWin();
}
this.menu.hide();
this.saveStoryWin.reference = this.ctxRecord.data.link;
this.saveStoryWin.show(this.ctxRecord.data.title, this.ctxRecord.data.link);
}
}
]
}




);
this.menu.on('hide', this.onContextHide, this);
}
e.stopEvent();
if (this.ctxRow) {
Ext.fly(this.ctxRow).removeClass('x-node-ctx');
this.ctxRow = null;
}
this.ctxRow = this.view.getRow(index);
this.ctxRecord = this.store.getAt(index);
Ext.fly(this.ctxRow).addClass('x-node-ctx');
this.menu.showAt(e.getXY());
},

onContextHide: function() {
if (this.ctxRow) {
Ext.fly(this.ctxRow).removeClass('x-node-ctx');
this.ctxRow = null;
}
},
onSelect: function(tom, dick, harry, brother) {

alert('in onselect');

},


togglePreview: function(show) {
this.view.showPreview = show;
this.view.refresh();
},
setDefaultSearchParameters: function(searchParams, useDefaults) { //sets undefined paramaters to default params.
if (useDefaults) { Ext.apply(searchParams, prefs); } //if usedefaults set, we copy all the default settings from the prefs global variable obkect
if (searchParams.strQuery == undefined || searchParams.strQuery == '') { searchParams.strQuery = '*'; } //fixes exception in noodle code, should check it out
// console.log(searchTerm);
if (searchParams.catId == undefined || searchParams.catId == '') { searchParams.catId = 'All'; }
if (searchParams.atleast == undefined || searchParams.atleast == '') { searchParams.atleast = ''; }
if (searchParams.exactphrase == undefined || searchParams.exactphrase == '') { searchParams.exactphrase = ''; }
if (searchParams.startDate == undefined || searchParams.startDate == '') { searchParams.startDate = ''; }
if (searchParams.endDate == undefined || searchParams.endDate == '') { searchParams.endDate = ''; }


this.Search(searchParams);

},
LatestNewsSearch: function(searchString) {
var searchParams = new Object();
if (searchParams.Text == undefined || searchParams.Text == '') { searchParams.Text = searchString; } //fixes exception in noodle code, should check it out
// console.log(searchTerm);
if (searchParams.catId == undefined || searchParams.catId == '') { searchParams.catId = 'All'; }
if (searchParams.mindate == undefined || searchParams.mindate == '') { searchParams.mindate = ''; }
if (searchParams.maxdate == undefined || searchParams.maxdate == '') { searchParams.maxdate = ''; }
if (searchParams.databasematch == undefined || searchParams.databasematch == '') { searchParams.databasematch = 'REUTERS,JANES'; }
this.Search(searchParams);


},
// within this function "this" is actually the GridView //FORMATS THE ROWS
applyRowClass: function(record, rowIndex, p, ds) {
if (this.showPreview) {
var xf = Ext.util.Format;
var teststring = xf.htmlEncode(record.data.description); //CRAIG , did this as some descs contained huge image tags which werent getting scrubbed
p.body = '<p>' + xf.ellipsis(teststring, 400) + '</p>'; //STRIP TAGS!!! //TODO determine optimum ellipsis length

var myregexp = new RegExp(Ext.escapeRe(this.grid.store.lastOptions.params.strQuery), 'gi');
p.body = p.body.replace(myregexp, "<font color=red>" + this.store.lastOptions.params.strQuery + "</font>");

return 'x-grid3-row-expanded';
}
return 'x-grid3-row-collapsed';
},

formatDate: function(date) {
if (!date) {
return '';
}
var now = new Date();
var d = now.clearTime(true);
var notime = date.clearTime(true).getTime();
if (notime == d.getTime()) {
return 'Today ' + date.dateFormat('g:i a');
}
d = d.add('d', -6);
if (d.getTime() <= notime) {
return date.dateFormat('D g:i a');
}
return date.dateFormat('n/j g:i a');
},

// formatTitle: function(value, p, record) {
// return String.format(
// // '<div class="topic"><b>{0}</b><span class="author">{1} {4}</span></div>',
// '<div ><b>{0}</b></div>', //CRAIG changed to make less cluttered
// value, record.data.database, record.id, record.data.forumid, record.data.foldername
// );
// }

formatIcons: function(value, p, record) {//takes a comma separated list of strings and generate image for each
//if no icons, return
if (value == '') { return; }

//remove trailing ,

var withouttrailingcomma = record.data.hoticons.replace(/\,$/, '');
//first split the string on ,
var arrayIcons = withouttrailingcomma.split(",");
var imageDiv = '<div>'
for (var i = 0; i < arrayIcons.length; i++) {
imageDiv += String.format('<img src="images/Icons/HotIcons/{0}.gif" />', arrayIcons[i]);

}
imageDiv += '</div>'
return imageDiv;



},

formatTitle: function(value, p, record) {


return String.format('<div><span onclick=\'window.open("{1}")\' > <b>{0}</b></span><br>{2} {3}</div>', record.data.title, String.escape(record.data.link), record.data.database, record.data.foldername
);

},

ExpandRow: function(expand, record, rowIndex, p, ds) { //p.body = the html fragment

if (expand) { //expand the row
// var xf = Ext.util.Format;
// var teststring = xf.htmlEncode(record.data.description); //CRAIG , did this as some descs contained huge image tags which werent getting scrubbed
// p.body = '<p>' + xf.ellipsis(teststring, 400) + '</p>'; //STRIP TAGS!!! //TODO determine optimum ellipsis length

// var myregexp = new RegExp(Ext.escapeRe(this.store.lastOptions.params.strQuery), 'gi');
// p.body = p.body.replace(myregexp, "<font color=red>" + this.store.lastOptions.params.strQuery + "</font>");
p.body = "TEST";

return 'x-grid3-row-expanded';
}
return 'x-grid3-row-collapsed'; //otherwise collapse the row

//remember to call view.refresh afterwords!!!!
}
});


this bit is the important bit if you can't see what I am doing in that big mess above:

this.on('rowcontextmenu', this.onContextClick, this);

//this event fires when the main grid's data is loaded (ie a new search has been performed). We use this event to update the suggestions grid, if there is one);
this.store.proxy.on('load', this.updateSuggestions, this);

};

Ext.extend(ResultsGrid, Ext.grid.GridPanel, {

updateSuggestions: function(callingProxy, xmldoc, callingProxyArgs) {

//try and find a suggestions gridpanel
var suggestionsGrid = Ext.getCmp('suggestions-grid');
if (suggestionsGrid == null) { return; }

//we have the grid, we now pass it a copy of the XML data we have just received from the server, we get back a datablock that can be passed to the store
var datablock = suggestionsGrid.store.reader.read(callingProxy.conn.response);

//pass this datablock to the suggestionsgrid store
suggestionsGrid.store.loadData(datablock);
suggestionsGrid.view.refresh();
//finished!
},

Is there a better way to access the response when a store loads via its reader?

jay@moduscreate.com
30 Jun 2009, 4:44 AM
setup a load event handler for the store to do what you want.

Vaevictus
30 Jun 2009, 5:25 AM
thanks for the reply, but I think what you suggest is no better than what I have got.

I have just fixed the issue.


this.store.proxy.on('load', this.updateSuggestions, this);

//simplified code for updateSuggestions:

updateSuggestions: function(callingProxy, xmldoc, callingProxyArgs) {
var suggestionsGrid = Ext.getCmp('suggestions-grid');
suggestionsGrid.store.loadData(xmldoc.reader.xmlData.childNodes);

}
suggestionsgrid.js:
//snip

this.store = new Ext.data.Store({
reader: new Ext.data.XmlReader(
{ record: 'suggestion' },
[{ name: 'suggestion', mapping: '', type: 'string' }
]
)

});

//snip

Condor
30 Jun 2009, 5:29 AM
Wouldn't it be easier to use:


store1.on('load', function(){
store2.loadData(store1.reader.xmlData);
});
store1.load()
(where store1 and store2 are configured with an XmlReader with a different 'record' config option)