EnhancedGrid within another EnhancedGrid - javascript

I'm using the dojo grid cell formatter to display an inner grid within another grid. Even though the inner grid is added, it does not display on the HTML page cause its height and width are 0px.
My JSP page and the JS page where the grids are created is shown below. Any help will be appreciated.
My guess is that calling grid.startup() in the cell formatter is probably not the right place. But where should I move the startup() call to -or- is there something else that needs to be done to get the inner grid to render correctly.
----JSP file ----
<script type="text/javascript"> dojo.require("portlets.ListPortlet"); var <portlet:namespace/>args = { namespace: '<portlet:namespace/>', listDivId: 'listGrid' }; var <portlet:namespace/>controller = new portlets.ListPortlet(<portlet:namespace/>args); dojo.addOnLoad(function(){ <portlet:namespace/>controller.init(); }); </script>
</div>
----JS file ----
dojo.declare("portlets.ListPortlet", null, {
constructor: function(args){
dojo.mixin(this,args);
this.params = args;
},
init: function(){
var layout = [[
{field: 'site', name: 'Site', width: '30px' }
{field: 'name', name: 'Full Name', width: '100px'},
{field: 'recordStatus', name: 'Status', width: '80px' }
],[
{field: '_item', name: ' ', filterable: false, formatter: this.formatNotesTable, colSpan: 3 }
]];
this.grid = new dojox.grid.EnhancedGrid({
autoHeight: true,
autoWidth: true,
selectable: true,
query:{
fromDate: start,
toDate: end
},
rowsPerPage: 10
});
this.grid.placeAt(dojo.byId(this.listDivId));
this.dataStore = new dojox.data.JsonRestStore({target: dataURL, idAttribute: idAttribute});
this.grid.setStructure(layout);
this.grid.startup();
},
formatNotesTable(rowObj) {
var gridData = {
identifier:"id",
items: [
{id:1, "Name":915,"IpAddress":6},
{id:2, "Name":916,"IpAddress":7}
]
};
var gridStructure = [{
cells:[
[
{ field: "Name",
name: "Name",
},
{ field: "IpAddress",
name: "Ip Address" ,
styles: 'text-align: right;'
}
]
]
}];
var gridStore = new dojo.data.ItemFileReadStore( { data: gridData} );
var cpane = new dijit.layout.ContentPane ({
content: "inner grid should be displayed below"
});
var subgrid = new dojox.grid.DataGrid({
store: gridStore,
structure: gridStructure,
style: {width: "325px", height: "300px"}
});
subgrid.placeAt(cpane);
subgrid.startup();
return cpane;
}
}

I solved my problem by using a dojox.layout.TableContainer inside the EnhancedGrid.

Related

Selecting rows from one grid & passing them to another grid

I'm trying to allow rows to be selected via checkboxes and for those selected rows and their IDs to be sent to another grid when a 'Submit' button is clicked. In other words, acting as some sort of filter.
I've contacted Telerik's support team and was advised to take the following steps in order to get it working:
Get the selected rows with the Select() method of the Grid
Loop through them & get the underlying item with the dataItem method
Save them into an array
Destroy the grid
Initialize a new grid by setting the data data
Here's a sample on JSBin that shows what I have in mind.
I'm not sure where to start honestly. I would really appreciate it if someone could point me in the right direction to any resources or guides that would be helpful. Thanks!
Assuming you are using RadGrid, make sure you have client side selection turned on, you would see something like this:
<ClientSettings>
<Selecting AllowRowSelect="True" />
<ClientEvents OnRowSelected="RowSelected" />
</ClientSettings>
On the input button, make sure to call your JS method as follows :
<input onclick="GetSelected();" .... >
Your JS code might look something like this :
function GetSelected() {
var grid = $find("<%=Your Grid's ClientID Here%>");
var MasterTable = grid.get_masterTableView();
var selectedRows = MasterTable.get_selectedItems(); // 1. Get the selected rows. The selected item can be accessed by calling the get_selectedItems() method of the GridTableView client-side object.
for (var i = 0; i < selectedRows.length; i++) {
var row = selectedRows[i];
// This is where you would have to insert it in a collection so that you can bind it to another grid... You will need to call .Rebind() once you assign the new datasource to the other grid.
}
Hopefully this will give you some idea.. I can see if I can find any examples on inserting rows into other grid if you get stuck.
check this code
html
<div id="grid1"></div>
<input type="button" value="Submit" onclick="Move()" />
<div id="grid2" ></div>
script
<script>
$(document).ready(function() {
var data1 = [
{ id: 1, rating: 3, year: 1997, title: "Rock" }
, { id: 2, rating: 5, year: 1999, title: "X-Man" }
, { id: 3, rating: 4, year: 2011, title: "World War Z" }
];
var grid1=$("#grid1").kendoGrid({
sortable: true
, silectable: true
, selectable: "multiple row"
, filterable: true
, pageable: true
, columns: [
{ template: "<input type='checkbox' class='checkbox' />", width: "40px" }
,{ field: "id", title: "Id", filterable: false }
, { field: "rating", title: "Rating", filterable: false }
, { field: "year", title: "Year", filterable: true, type: "string"}
, { field: "title", title: "Title" }
]
, dataSource: { page: 1,
pageSize: 5,
data: data1
}
}).data("kendoGrid");
grid1.table.on("click", ".checkbox", selectRow);
var data2 = [
{ id: 101, rating: 6, year: 2012, title: "The Impossible" }
, { id: 102, rating: 8, year: 2013, title: "Escape" }
, { id: 103, rating: 7, year: 2013, title: "Gravity" }
];
$("#grid2").kendoGrid({
sortable: true
, silectable: true
, selectable: "multiple row"
, filterable: true
, pageable: true
, columns: [
{ field: "id", title: "Id", filterable: false }
, { field: "rating", title: "Rating", filterable: false }
, { field: "year", title: "Year", filterable: true, type: "string"}
, { field: "title", title: "Title" }
]
, dataSource: { page: 1,
pageSize: 5,
data: data2
}
});
});
function Move() {
var grid1 = $("#grid1").data("kendoGrid");
var rows = grid1.select();
rows.each(function(index, row) {
var selectedRow = grid1.dataItem(row);
//-move to grid2
var grid2 = $("#grid2").data("kendoGrid");
var ins = { id: selectedRow.id, rating: selectedRow.rating, year: selectedRow.year, title: selectedRow.title }; //id=1,rating=9.2,year=1995,title="The Godfather"
grid2.dataSource.insert(ins);
});
rows.each(function() {
grid1.removeRow($(this).closest('tr'));
});
}
function selectRow() {
var checked = this.checked,
row = $(this).closest("tr");
if (checked) {
//-select the row
row.addClass("k-state-selected");
} else {
//-remove selection
row.removeClass("k-state-selected");
}
}
</script>
this will help you :)

ExtJS 4.1 Infinite Grid Scrolling doesnt work with Dynamic store using loadData

I have to load first grid panel on tab and then load data into store using loadData() function which is working fine, but now I have to integrate infinite grid scrolling with it.
Is there any way to integrate infinite scrolling on fly after loadData into store..? I am using ExtJS 4.1. Please help me out.
Here I am showing my current script in controller and grip view panel in which I have tried out but not working.
Controller Script as below:
var c = this.getApplication().getController('Main'),
data = c.generateReportGridConfiguration(response,true),
tabParams = {
title: 'Generated Report',
closable: true,
iconCls: 'view',
widget: 'generatedReportGrid',
layout: 'fit',
gridConfig: data
},
generatedReportGrid = this.addTab(tabParams);
generatedReportGrid.getStore().loadData(data.data);
On Above script, once I get Ajax call response, adding grid panel with tabParams and passed data with gridConfig param which will be set fields and columns for grid and then last statement supply grid data to grid. I have tried out grid panel settings by following reference example:
http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/infinite-scroll.html
On above page, Included script => http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/infinite-scroll.js
My Grid Panel Script as below:
Ext.define('ReportsBuilder.view.GeneratedReportGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.generatedReportGrid',
requires: [
'ReportsBuilder.view.GenerateViewToolbar',
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.grid.PagingScroller',
'Ext.grid.RowNumberer',
],
initComponent: function() {
Ext.define('Report', {extend: 'Ext.data.Model', fields: this.gridConfig.fields, idProperty: 'rowid'});
var myStore = Ext.create('Ext.data.Store', {model: 'Report', groupField: 'name',
// allow the grid to interact with the paging scroller by buffering
buffered: true,
pageSize: 100,
autoSync: true,
extraParams: { total: 50000 },
purgePageCount: 0,
proxy: {
type: 'ajax',
data: {},
extraParams: {
total: 50000
},
reader: {
root: 'data',
totalProperty: 'totalCount'
},
// sends single sort as multi parameter
simpleSortMode: true
}
});
Ext.apply(this, {
dockedItems: [
{xtype: 'generateviewToolbar'}
],
store: myStore,
width:700,
height:500,
scroll: 'vertical',
loadMask: true,
verticalScroller:'paginggridscroller',
invalidateScrollerOnRefresh: false,
viewConfig: {
trackOver: false,
emptyText: [
'<div class="empty-workspace-bg">',
'<div class="empty-workspace-vertical-block-message">There are no results for provided conditions</div>',
'<div class="empty-workspace-vertical-block-message-helper"></div>',
'</div>'
].join('')
},
columns: this.gridConfig.columns,
features: [
{ftype: 'groupingsummary', groupHeaderTpl: '{name} ({rows.length} Record{[values.rows.length > 1 ? "s" : ""]})', enableGroupingMenu: false}
],
renderTo: Ext.getBody()
});
// trigger the data store load
myStore.guaranteeRange(0, 99);
this.callParent(arguments);
}
});
I have also handled start and limit from server side query but it will not sending ajax request on scroll just fired at once because pageSize property in grid is 100 and guaranteeRange function call params are 0,99 if i will increased 0,299 then it will be fired three ajax call at once (0,100), (100,200) and (200,300) but showing data on grid for first ajax call only and not fired on vertical scrolling.
As, I am new learner on ExtJs, so please help me out...
Thanks a lot..in advanced.
You cannot call store.loadData with a remote/buffered store and grid implementation and expect the grid to reflect this new data.
Instead, you must call store.load.
Example 1, buffered store using store.load
This example shows the store.on("load") event firing.
http://codepen.io/anon/pen/XJeNQe?editors=001
;(function(Ext) {
Ext.onReady(function() {
console.log("Ext.onReady")
var store = Ext.create("Ext.data.Store", {
fields: ["id", "name"]
,buffered: true
,pageSize: 100
,proxy: {
type: 'rest'
,url: '/anon/pen/azLBeY.js'
reader: {
type: 'json'
}
}
})
store.on("load", function(component, records) {
console.log("store.load")
console.log("records:")
console.log(records)
})
var grid = new Ext.create("Ext.grid.Panel", {
requires: ['Ext.grid.plugin.BufferedRenderer']
,plugins: {
ptype: 'bufferedrenderer'
}
,title: "people"
,height: 200
,loadMask: true
,store: store
,columns: [
{text: "id", dataIndex: "id"}
,{text: "name", dataIndex: "name"}
]
})
grid.on("afterrender", function(component) {
console.log("grid.afterrender")
})
grid.render(Ext.getBody())
store.load()
})
})(Ext)
Example 2, static store using store.loadData
You can see from this example that the store.on("load") event never fires.
http://codepen.io/anon/pen/XJeNQe?editors=001
;(function(Ext) {
Ext.onReady(function() {
console.log("Ext.onReady")
var store = Ext.create("Ext.data.Store", {
fields: ["id", "name"]
,proxy: {
type: 'rest'
,reader: {
type: 'json'
}
}
})
store.on("load", function(component, records) {
console.log("store.load")
console.log("records:")
console.log(records)
})
var grid = new Ext.create("Ext.grid.Panel", {
title: "people"
,height: 200
,store: store
,loadMask: true
,columns: [
{text: "id", dataIndex: "id"}
,{text: "name", dataIndex: "name"}
]
})
grid.on("afterrender", function(component) {
console.log("grid.afterrender")
})
grid.render(Ext.getBody())
var data = [
{'id': 1, 'name': 'Vinnie'}
,{'id': 2, 'name': 'Johna'}
,{'id': 3, 'name': 'Jere'}
,{'id': 4, 'name': 'Magdalena'}
,{'id': 5, 'name': 'Euna'}
,{'id': 6, 'name': 'Mikki'}
,{'id': 7, 'name': 'Obdulia'}
,{'id': 8, 'name': 'Elvina'}
,{'id': 9, 'name': 'Dick'}
,{'id': 10, 'name': 'Beverly'}
]
store.loadData(data)
})
})(Ext)

Get Grid Cell Value on Hover in ExtJS4

I have the following code in a grid:
var grid = Ext.create('Ext.grid.Panel', {
store: store,
stateful: true,
stateId: 'stateGrid',
columns: [
{
text : 'Job ID',
width : 75,
sortable : true,
dataIndex: 'id'
},
{
text : 'File Name',
width : 75,
sortable : true,
dataIndex: 'filename',
listeners : {
'mouseover' : function(iView, iCellEl,
iColIdx, iRecord, iRowEl, iRowIdx, iEvent) {
var zRec = iView.getRecord(iRowEl);
alert(zRec.data.id);
}
}
...etc...
I can't figure out how to get the cell value of the first column in the row. I've also tried:
var record = grid.getStore().getAt(iRowIdx); // Get the Record
alert(iView.getRecord().get('id'));
Any ideas?
Thanks in advance!
It's easier than what you have.
Look at the Company column config here for an example-
http://jsfiddle.net/qr2BJ/4580/
Edit:
Part of grid definition code:
....
columns: [
{
text : 'Company',
flex : 1,
sortable : false,
dataIndex: 'company',
renderer : function (value, metaData, record, row, col, store, gridView) {
metaData.tdAttr = 'data-qtip="' + record.get('price') + ' is the price of ' + value + '"';
return value;
}
},
....
You can add a handler instead of a listener.
{
header: 'DETAILS',
xtype:'actioncolumn',
align:'center',
width: 70,
sortable: false,
items: [
{
icon: '/icons/details_icon.png', // Use a URL in the icon config
tooltip: 'Show Details',
handler: function(grid, rowIndex, colIndex) {
var record = grid.getStore().getAt(rowIndex);
}

ExtJS GridPanel width

I'm using Ext JS 2.3.0 and have created the search dialog shown below.
The search results are shown in a GridPanel with a single Name column, but notice that this column does not stretch to fill all the available horizontal space. However, after I perform a search, the column resizes properly (even if no results are returned):
How can I make the column display correctly when it's shown initially? The relevant code is shown below:
FV.FindEntityDialog = Ext.extend(Ext.util.Observable, {
constructor: function() {
var queryTextField = new Ext.form.TextField({
hideLabel: true,
width: 275,
colspan: 2,
});
var self = this;
// the search query panel
var entitySearchForm = new Ext.form.FormPanel({
width: '100%',
frame: true,
layout:'table',
layoutConfig: {columns: 3},
items: [
queryTextField,
{
xtype: 'button',
text: locale["dialogSearch.button.search"],
handler: function() {
var queryString = queryTextField.getValue();
self._doSearch(queryString);
}
}
]
});
// the search results model and view
this._searchResultsStore = new Ext.data.SimpleStore({
data: [],
fields: ['name']
});
var colModel = new Ext.grid.ColumnModel([
{
id: 'name',
header: locale['dialogSearch.column.name'],
sortable: true,
dataIndex: 'name'
}
]);
var selectionModel = new Ext.grid.RowSelectionModel({singleSelect: false});
this._searchResultsPanel = new Ext.grid.GridPanel({
title: locale['dialogSearch.results.name'],
height: 400,
stripeRows: true,
autoWidth: true,
autoExpandColumn: 'name',
store: this._searchResultsStore,
colModel: colModel,
selModel: selectionModel,
hidden: false,
buttonAlign: 'center',
buttons: [
{
text: locale["dialogSearch.button.add"],
handler: function () {
entitySearchWindow.close();
}
},
{
text: locale["dialogSearch.button.cancel"],
handler: function () {
entitySearchWindow.close();
}
}
]
});
// a modal window that contains both the search query and results panels
var entitySearchWindow = new Ext.Window({
closable: true,
resizable: false,
draggable: true,
modal: true,
viewConfig: {
forceFit: true
},
title: locale['dialogSearch.title'],
items: [entitySearchForm, this._searchResultsPanel]
});
entitySearchWindow.show();
},
/**
* Search for an entity that matches the query and update the results panel with a list of matches
* #param queryString
*/
_doSearch: function(queryString) {
def dummyResults = [['foo'], ['bar'], ['baz']];
self._searchResultsStore.loadData(dummyResults, false);
}
});
It's the same issue you had in an earlier question, the viewConfig is an config item for the grid panel check the docs , so it should be
this._searchResultsPanel = new Ext.grid.GridPanel({
viewConfig: {
forceFit: true
},
....other configs you need,
To be more precise the viewConfig accepts the Ext.grid.GridView configs, feel free to read the docs on that one too.
Otherwise this seems to be the only problem, and i refer the column width, not the gridpanel width. On the gridpanel you have a title and two buttons who doesn't seem to be affected. So i repeat the gridPanel's width is ok, it's the columns width issue.
Try to remove autoWidth from GridPanel configuration, because setting autoWidth:true means that the browser will manage width based on the element's contents, and that Ext will not manage it at all.
In addition you can try to call .doLayout(false, true) on your grid after it was rendered.
Try to add flex: 1 to your GridPanel

Checkbox Selection + Grid Panel with Summary Row in ExtJS 4

given the following Grid Panel:
Ext.onReady(function() {
var sm = new Ext.selection.CheckboxModel( {
listeners:{
selectionchange: function(selectionModel, selected, options){
// Bunch of code to update store
}
}
});
var grid = Ext.create('Ext.grid.Panel', {
features: [{
ftype: 'summary'
}],
store: store,
defaults: { // defaults are applied to items, not the container
sortable:true
},
selModel: sm,
columns: [
{header: 'Column 1', flex: 1, dataIndex: 'd1', summaryRenderer: function(value, summaryData, dataIndex) { return "Selected Data"} },
{header: 'C2', width: 150, dataIndex: 'd2', summaryType: 'sum'},
{header: 'C3', width: 150, dataIndex: 'd3', renderer: dRenderer, summaryType: 'sum'},
{header: 'C4', width: 150, dataIndex: 'd4', renderer: dRenderer, summaryType: 'sum'},
{header: 'C5', width: 150, renderer: total, summaryRenderer: grandTotal}
],
width: "100%",
title: 'Grid',
renderTo: 'grid',
viewConfig: {
stripeRows: true
}
});
});
How does this need to be refactored to summarize the data of only those rows that are selected? I know that I probably need to override the sum function of the Summary Feature, but haven't been able to find an example or proper syntax in the docs.
Thanks!
Here was my attempt at a solution (posted on the Sencha 4.x help forum w/ no responses):
Ext.define('Ext.grid.feature.SelectedSummary', {
extend: 'Ext.grid.feature.Summary',
alias: 'feature.selectsummary',
generateSummaryData: function(){
var me = this,
data = {},
store = me.view.store,
selectedRecords = me.view.selModel.selected,
columns = me.view.headerCt.getColumnsForTpl(),
i = 0,
length = columns.length,
fieldData,
key,
comp;
for (i = 0, length = columns.length; i < length; ++i) {
comp = Ext.getCmp(columns[i].id);
val = 0;
for(j = 0, numRecs = selectedRecords.items.length; j < numRecs; j++ ) {
field = columns[i].dataIndex;
rec = selectedRecords.items[j];
console.log(rec.get(field));
val += rec.get(field);
}
data[comp.dataIndex] = val;//me.getSummary(store, comp.summaryType, comp.dataIndex, false);
}
return data;
}
});
But this only renders correctly on initial render and only renders when I step through the code with a debugger. There's some kind of race condition where the row gets rendered without the calculations being completed.
Any ideas? Is my question too specific? Perhaps just simple pointers on writing my own feature and adding it to a Grid Panel.
Solution from a colleague:
The summary feature has the capability to take a function as the summaryType. Because the column config does not get passed to this function by default you need to define a closure that will hold on to the dataIndex.
var sm = new Ext.selection.CheckboxModel( {
listeners:{
selectionchange: function(selectionModel, selected, options){
// Must refresh the view after every selection
myGrid.getView().refresh();
// other code for this listener
}
}
});
var getSelectedSumFn = function(column){
return function(){
var records = myGrid.getSelectionModel().getSelection(),
result = 0;
Ext.each(records, function(record){
result += record.get(column) * 1;
});
return result;
};
}
// create the Grid
var myGrid = Ext.create('Ext.grid.Panel', {
autoScroll:true,
features: [{
ftype: 'summary'
}],
store: myStore,
defaults: { // defaults are applied to items, not the container
sortable:true
},
selModel: sm,
columns: [
{header: 'h0', flex: 1, dataIndex: 'groupValue'},
{header: 'h1', width: 150, dataIndex: 'd1', summaryType: getSelectedSumFn('d1')},
{header: 'h2', width: 150, dataIndex: 'd2', renderer: r, summaryType: getSelectedSumFn('d2')},
{header: 'h3', width: 150, dataIndex: 'd3', renderer: r, summaryType: getSelectedSumFn('d3')},
{header: 'h4', width: 150, dataIndex: 'd4', renderer: r, summaryType: getSelectedSumFn('d4')}
],
width: "100%",
height: "300",
title: 'Data',
renderTo: 'data',
viewConfig: {
stripeRows: true
}
});
A little bit updated previous solution:
var sm = new Ext.selection.CheckboxModel({
listeners: {
selectionchange: function (selectionModel, selected, options) {
// Must refresh the view after every selection
selectionModel.view.refresh();
}
}
});
var getSelectedSumFn = function (column, selModel) {
return function () {
var records = selModel.getSelection(),
result = 0;
Ext.each(records, function (record) {
result += record.get(column) * 1;
});
return result;
};
};
and then in grid use following line:
summaryType: getSelectedSumFn('d4', sm)}

Categories

Resources