PDA

View Full Version : How to create a grid with dynamic number of columns



rahulpatel
2 Mar 2012, 1:01 PM
I need to create a grid where in the number of columns changes based on a method that returns a set of Strings from the server.
If I use a BeanModel, I have to specify the class that declares the model to use but in this case I cannot assign a variable for each column before hand.
This Grid is supposed to be paginated as well and all examples I have seen bind a loader with the grid store in the following manner:

keyStore = new ListStore<BeanModel>(keysLoader);
Am not sure how I can use the Loader if I have a dynamic set of columns.

So if it was just a simple grid without paging. I could have setup the store as follows:

public class MyDataObject
{
String type;
String value;
}


public void setUpStore(List<List<MyDataObject>> data)
{
List<BaseModelData> baseModelDataList = new ArrayList<BaseModelData>();

for(List<MyDataObject> dataList : data)
{
for(MyDataObject dataObject: dataList)
{
BaseModelData modelData = new BaseModelData();
modelData.set(dataObject.getType(), dataObject.getValue());
}
baseModelDataList.add(modelData);
}
store.add(baseModelDataList); // I would create the grid columns by iterating over the
// List<MyObject> and using the type field to set the column ids.
}

But not sure how to do the same via a loader.

Please help.

Thank you.

dariusjb
5 Mar 2012, 12:48 AM
First of all, it is possible.

You can reconfigure a grid component.
Therefore, you must init your grid, keeping all needed objects init by the create calls, and re-use them to reconfigure your grid again.

To have dynamic column, write your code once, the one configuring the column, in a separate method, when time is to update, let say after the load of your data, you reconfigure the grid, processing your incoming data to create your columnconfig again.

For your info, you don't have to bind a loader, but if you do so, and that you have a specific BeanModel, you need to implement a BeanModelReader. Mastering this, can take sometime. But if you simply want to load, just process your String list, into your store when you want to update your data.
If you want to use the GXT paging system, I m afraid you will have to create a loader.

Here a simple snippet for paging

/**
* Paging Reader for BeanModel
*/
private final BeanModelReader reader = new BeanModelReader() {
@Override
protected ListLoadResult<ModelData> newLoadResult(Object loadConfig, List<ModelData> models) {
return new BasePagingLoadResult<ModelData>(models);
}
};
PagingModelMemoryProxy proxy = new PagingModelMemoryProxy(new ArrayList<YourBeanModel>());
final PagingLoader<PagingLoadResult<BeanModel>> loader = new BasePagingLoader<PagingLoadResult<BeanModel>>(proxy, reader);
// Create Store
Store<BeanModel> store = new Store<BeanModel>(loader);

PagingToolBar pgToolBar = new PagingToolBar(nbItemsByPage);
pgToolBar.bind(loader);

Grid<BeanModel> grid = new Grid<BeanModel>(store, cm);

I can provide you a more code snippet, but you are asking 2 questions: dynamic column and paging with data load.

rahulpatel
5 Mar 2012, 5:29 AM
Thanks for helping me out!

I do need to use the loader. Our table has to load around 15,000 rows of data and it requires remote paging. I use the RpcProxy<PagingLoadResult<MyDataObject>> class to do use the rpc based paging. I am aware how to use the Loader for grids with static columns but am not sure how to do this for dynamic columns. For static columns I just have to use the BeanMarker to mark my data object class and make sure the grid column ids match the variable names. But as you can see this strategy will not work for a grid with dynamic columns. Can you please show me how to setup the loader for dynamic columns. Thanks.

dariusjb
5 Mar 2012, 8:05 AM
Well,

You can also use an RpcProxy<List<BeanModel>> to create your columns:
Here my definition with Column, being a POJO with a Marked BeanModel interface on side.

RpcProxy<List<Column>> proxyCol = new RpcProxy<List<Column>>() {
@Override
public void load(Object loadConfig, AsyncCallback<List<Column>> callback) {
logger.fine("loading column data");
myRpcService.getColumn(callback);
}
};

final ListLoader<ListLoadResult<BeanModel>> loaderCol= new BaseListLoader<ListLoadResult<BeanModel>>(proxyCol, new BeanModelReader());
ListStore<BeanModel> colStore = new ListStore<BeanModel>(loaderCol);
colStore.addListener(Store.DataChanged, new Listener<BaseEvent>() {
@Override
public void handleEvent(BaseEvent be) {
refreshGridColumn();
logger.fine("data has changed for column");
}
});

When the grid get attached, I manually force the loader to load: colStore.getLoader().load();
I refresh the grid view.

My refreshGridColumn is just going through my ColumnModel object from the grid,
I loop on my colStore when the data changed, the Store should contain something,
and i create every columnConfig based on the info from my Column list.
For the grid to update, you simply need to refresh the grid view.

Always make sure that you clear first the columnconfigs old info.

Also to manage the GXT filters, I go on the same time, through the Grid Plugin, try to reuse the filter in place.

My Column data, has consistent info on the type of column, and shared the same key as one info from my data store for the grid content.

As you may need column when creating your grid, just do it with an empty list of data. Then when your loader has all info, the grid must be refreshed. It will used the data available, depending on the column property to display these info while drawing every row/cell.

If really you need to make something to join your data from model, with the column property.
You can sheat, adding a gridcell renderer on the first column, making sure it will at init time, pass all info from your model POJO to the BeanModel with something consistent with your grid column property key.

rahulpatel
5 Mar 2012, 8:26 AM
I got what you are doing, just not sure what your Column class looks like. Can you please post the Column class ? Thanks.

rahulpatel
5 Mar 2012, 12:52 PM
Got it to work! Thanks a lot!