PDA

View Full Version : ext gs grid slowwww with my database, any ideas why?



lexusgs430
11 Aug 2010, 4:26 PM
Hey,

So today is my first day using ext js and it seems pretty slick. But Im having some troubles getting it to work with a semi large database of 7k records or so. Im loading the data for the grid using ext.data.httpproxy, and Im targeting a url on my site which grabs the data from my database and outputs it as json, that part is happening super quickly. But basically, when the grid actually renders, it takes probably 15 seconds or so and I get the spinning beachball of doom during those 15 seconds. But after it renders, if I want to do anything like sort the grid, or even grid unrelated stuff like close the west section (im using the border deal for layout) -- it takes another 15 seconds to complete the action.

P.S., im using codeigniter and trying to make a super modular wrapper type solution for ext js, so Im basically creating the grid render script in the view (hopefully that wont confuse any of u not familiar with codeigniter) -- but basically, the ext-all and base are being linked to in the header of my page, but Im calling the actual get dummy center panel, replace it with the grid, on the individual view page. I dont THINK that should cause a problem.. but Im really not sure, and that is what the code at the top of my referenced code is doing.

Anyways, here is my code, and any help much appreciated.

Thanks

(btw thread title is supposed to read ext JS, obviously :D, but I cant seem to edit title)


<script type="text/javascript">

Ext.onReady(function(){

pageContent = new Ext.Panel({
title : 'Page Title',
html : '<div id="main-content"></div>'
});

p = Ext.getCmp('panel');
ctrContainer = Ext.getCmp('centerRegion');

ctrContainer.remove(p, true);

ctrContainer.add(pageContent);

ctrContainer.doLayout();

var dataRecord = new Ext.data.Record.create([
{name: 'id'},
{name: 'sku'},
{name: 'name'},
{name: 'brand'}
]);

var dataReader = new Ext.data.JsonReader({
root: 'results'
},
dataRecord
);

var dataProxy = new Ext.data.HttpProxy({
url: <?php echo "'".base_url()."index.php/site/js_inventory/'"; ?>,
method: 'POST'
});

var dataStore = new Ext.data.Store({
proxy: dataProxy,
remoteSort: true,
reader: dataReader
});

var colModel = new Ext.grid.ColumnModel([
{header: "id", dataIndex: 'id', width: 10},
{header: "sku", dataIndex: 'sku', width:20},
{header: "name", dataIndex: 'name'},
{header: "brand", sortable: true, dataIndex: 'brand'}
]);

var grid = new Ext.grid.GridPanel({
autoHeight: true,
renderTo: 'main-content',
store: dataStore,
id: 'grid',
width: 740,
viewConfig: {
forceFit: true
},
cm: colModel
});

dataStore.load();

});
</script>

darthwes
11 Aug 2010, 5:27 PM
Hello. You probably want to use a viewport. You can get away without it, but it makes life so much simpler to have. It also helps to see how others declare stores and grids. Let me show you how I would do it, first.



Ext.onReady(function(){
var dataStore = new Ext.data.JsonStore({
method: 'POST',
autoLoad: true,
root: 'results',
fields: ['id', 'sku', 'name', 'brand'],
url: 'test.php', //whatever
remoteSort: true
});

var colModel = new Ext.grid.ColumnModel([
{header: "id", dataIndex: 'id', width: 10},
{header: "sku", dataIndex: 'sku', width:20},
{header: "name", dataIndex: 'name'},
{header: "brand", sortable: true, dataIndex: 'brand'}
]);

var grid = new Ext.grid.GridPanel({
region: 'center',
store: dataStore,
viewConfig: {
forceFit: true
},
cm: colModel
});

var view = new Ext.Viewport({
layout: 'border',
items:[grid]
});
});


So I layed the viewport down last with all the components already initialized. There is no reason to do any fancy adds/removes from a container. I also see that you're playing with the idea of using applyTo, renderTo, and/or contentEl. I urge you to find a solution that does not use those properties.

As for creating dynamic content, you can do fancy things with card layouts which will hide and show different "cards". The best example of this is a TabPanel. There's a class for that and you can essentially implement the same strategy of building up a content page inside the scope of a function and then returning a panel.

I would stress to you the importance of reading through the layout docs you can find (saki has a good one) and determining what your going to be putting, where, and how it's going to get sized. A viewport is the basic starting block for that.

Onwards: Performance. The only solution I'm aware of (and I've seen quite a few of these threads) is paging. The idea is that you will limit your SQL query down to some smaller size (say 50 or 100) and the grid will provide a paging bar that allows the user to flip through the pages of the result. So you only load a few records into memory at any one time. Javascript is not a good place to put thousands and thousands of records, most browsers flip out and become quite sticky to debug/troubleshoot.

Clearly you are quite clever if this is your first day, I take it on faith that you can find the pertinent documentation for the PagingToolBar class. Of course, we will gladly help if you post code examples!

lexusgs430
11 Aug 2010, 5:36 PM
sweet, thanks for such a detailed reply. That's exactly what I needed to see different ways of doing things. Ill read up more on viewports tonight, and ya I guess serverside paging is the way to go.

lexusgs430
11 Aug 2010, 5:41 PM
oh btw do you happen to have a link to the "saki layout doc" referenced above? I searched but couldnt find it.

darthwes
11 Aug 2010, 5:54 PM
Sure, no problem. Good luck. (http://examples.extjs.eu/)

lexusgs430
12 Aug 2010, 11:20 AM
Thanks for the link!

Ok so I am back at trying to figure out the best way to do things. I forgot to mention one important thing in my original post, which is the code I am using in my main php template, which is using the viewport. So the code I posted was for one individual page component, that way I can still use my php framework to manage the structure of the site and what not. But ya, basically, I am defining the viewport in the main file, and the reason im using the "remove center container, insert new one", is because I want the center container to change depending on the page content. (the viewport containers minus the center container, will be static and will contain the actual page nav for my site).

So my question is, is there a better solution than what I am doing now, to keep the php paging structure, while still using the viewport to create the page layout? (here is the code I am using, in my "header" php file.


<script type="text/javascript">

Ext.onReady(function() {
new Ext.Viewport({
layout : 'border',
defaults : {
height : 100,
width : 160,
collapsible : true
},
items : [
{
xtype : 'container',
layout : 'fit',
region : 'center',
id : 'centerRegion',
items : {
title : 'Fake Center Region',
id : 'panel'
}
},
{
title : 'North Panel',
region : 'north',
margins : '0 0 5 0'
},
{
title : 'South Panel',
region : 'south',
margins : '5 0 0 0'
},
{
title : 'West Panel',
region : 'west',
margins : '0 5 0 0'
},
{
title : 'East Panel',
region : 'east',
margins : '0 0 0 5'
}
]
});
});

</script>----- oh and I had an another idea that I initially dismissed as too makeshift, but after thinking about it, might work...

But basically, I was thinking I could write the opening part of the viewports script in the header template, and not close the script tag until the footer, which would allow me to choose a different panel for the center container on each page.

E.X.

header.php


<script type="text/javascript">

Ext.onReady(function() {
new Ext.Viewport({
layout : 'border',
defaults : {
height : 100,
width : 160,
collapsible : true
},
items : [-- then a php template for each region, e.g.
northpanel.php



{
title : 'North Panel',
region : 'north',
margins : '0 0 5 0'
},then footer.php


]
});
});

</script>

Php main template would look like

$this->load->view('header.php');
$this->load->view('northpanel.php'); // which would let me split each panel into diff file, north, south east west..
$this->load->view($main_content); // referencing the controller determined center content panel
$this->load->view('footer.php');

Then the center panel would be determined by my php controller file, on a per page basis.

The more I think about it the more I think this might be the way to go? Any thoughts?

darthwes
12 Aug 2010, 1:37 PM
Sure. Why not determine what include file has your content, grab it in php as a string and then echo it down so js sees it as if it's static. a la:

in the template:


<?php
//I would determine the include ('content3.php')
include('content3.php');
...
$thisPageContent = getContentPanel();
echo ("\nvar pageContent = $thisPageContent\n");
?>
new Ext.ViewPort({
...
items:[pageContent, staticWest, staticEast, staticNorth, staticSouth]
});


and content3.php (content2.php, content28.php, whatever):


function getContentPanel() {
$str = "new Ext.grid.GridPanel({
...
});";
return $str;
}


That close? You can use the same logic to simply include the correct js file and have seperate js files for each content page you want to show, make them all declare the same function like getContentPanel, only include the one you want, and call it up as you build the viewport.