PDA

View Full Version : Aggregation Column?



lmivan
29 Aug 2009, 3:00 PM
Hello,

I have a grid in which every row is a transaction (with transaction name, description and amount). The grid is displayed correctly but I want to add a new column with the total of the transactions until every row, I mean (the total column is not in my data, I generate it on the fly):



NAME DESC AMOUNT TOTAL
n1 d1 10 10
n2 d2 -5 5
n3 d3 -20 -15
n4 d4 50 35

I'm using the following GridCellRender:



private double totalRow = 0.0;
...
...
column = new ColumnConfig();
column.setHeader(constants.total());
column.setWidth(80);
column.setRenderer(new GridCellRenderer<BeanModel>() {
@Override
public Object render(BeanModel model, String property, ColumnData config,
int rowIndex, int colIndex, ListStore<BeanModel> store,
Grid<BeanModel> grid) {

Double tranAmount = model.get("transactionAmount");
totalRow += tranAmount;

// Return the total accumulated until this row
return MuflyUtils.numberFormater.format(totalRow);
}
});
columns.add(column);and it's working ok the first time the grid is displayed, but when I scroll down to the last row and then scroll up to the first row, all the amounts are accumulated again. Am I doing something wrong?. Is there any way to not accumulate the amounts all the time.

Additional info: I'm using the Page BeanModel Grid example as the base for my test.

Regards, Iván.

lmivan
30 Aug 2009, 7:24 AM
More info. I've discoreved that with the paging bean model example it is working properly, but if I add the following code the previously problem is reproduced.



BufferView view = new BufferView();
view.setScrollDelay(0);
view.setAutoFill(true);

grid = new Grid<BeanModel>(store, cm);
grid.setView(view);
With this code the render of the grid is done too fast but the values are accumulated more than one time.
Is there any way to solve my problem?.

Thanks and regards, Iván.

Arno.Nyhm
31 Aug 2009, 4:38 AM
maybe its better to calculate it before you display the data:

a) loop the store and calculate it there. save it in a field in your model
b) it would be nice if a gridview has also a modelprocessor:
http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/ListView.html#setModelProcessor(com.extjs.gxt.ui.client.data.ModelProcessor) (http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/ListView.html#setModelProcessor%28com.extjs.gxt.ui.client.data.ModelProcessor%29)

like requested here http://www.yui-ext.com/forum/showthread.php?p=362910

Arno.Nyhm
31 Aug 2009, 4:40 AM
a) you can loop the store bevor you display the values.

b) a modelprocessor would be nice at gridview, but they is not there :-(
http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/ListView.html#setModelProcessor(com.extjs.gxt.ui.client.data.ModelProcessor) (http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/ListView.html#setModelProcessor%28com.extjs.gxt.ui.client.data.ModelProcessor%29)

(like requested also here: http://www.yui-ext.com/forum/showthread.php?p=362910 )

sven
31 Aug 2009, 4:42 AM
More info. I've discoreved that with the paging bean model example it is working properly, but if I add the following code the previously problem is reproduced.



BufferView view = new BufferView();
view.setScrollDelay(0);
view.setAutoFill(true);

grid = new Grid<BeanModel>(store, cm);
grid.setView(view);
With this code the render of the grid is done too fast but the values are accumulated more than one time.
Is there any way to solve my problem?.

Thanks and regards, Iván.

A renderer is called each time a cell gets rendered. So it is not the correct place to do calculations.

Arno.Nyhm
31 Aug 2009, 5:09 AM
there are plans to implement the ModelProcessor also to the GridView?

sven
31 Aug 2009, 5:14 AM
there are plans to implement the ModelProcessor also to the GridView?

No, also i dont see a good point for this. In a Grid you can define a custom cell renderer for each cell. With that you can format your data.

Arno.Nyhm
31 Aug 2009, 5:27 AM
ok.

- but with a cellrender i render a cell - each time if its rendered
- with a ModelProcessor i change the base data from store. this should be done before displaying the data.

ok. i looked into ListView. the ModelProcessor is also called each time if it is rendered. so for this use case it is not needed.

but generaly i think it is a good idea to have this modelprocessor also in a gridview. it is more easy to add a column with this.

lmivan
31 Aug 2009, 1:14 PM
maybe its better to calculate it before you display the data:
a) loop the store and calculate it there. save it in a field in your model


Thanks for the reply. Where I can do the loop and how save it in a field in my model?.

My model is an hibernate table, how i can add a new field in my model to display in the grid without modifying the database (Transaction.java class)?.
Transaction.java


@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

public class Transaction extends LightEntity implements Serializable {

private static final long serialVersionUID = -4794001131832566810L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;

@ManyToOne(optional = true)
protected Transaction parent;

@Column(nullable = false)
protected Boolean hasChilds;

@Column(nullable = false)
protected String transactionDesc;

@Column(nullable = false)
protected TransactionType transactionType;

@Column(nullable = false)
protected Double transactionAmount;

@Column(nullable = false)
protected Date transactionDate;

@Column(nullable = true)
protected String transactionComment;

@ManyToOne(optional=false)
protected Account account;

@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }) //, fetch=FetchType.EAGER)
protected Set<Tag> tags = new HashSet<Tag>();
Where I can do the loop, I mean, which method should a override o when I call my method that iterate the store and do the calculation?.

As you can see I'm new in GXT and I'm a little bit lost...

Thanks a lots!! :-D.

Regards, Iván.

lmivan
31 Aug 2009, 1:15 PM
A renderer is called each time a cell gets rendered. So it is not the correct place to do calculations.

So, where is the correct place to do the calculations?.

Thanks and regards, Iván.

Arno.Nyhm
1 Sep 2009, 4:48 AM
i dont know it exactly but i think your beans is a also have the ModelData interface with this you can always add values to it with myModel.set("paramtername", value)

http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/data/ModelData.html#set(java.lang.String,%20X) (http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/data/ModelData.html#set%28java.lang.String,%20X%29)


whats about to take the store and loop over the items after a loading?

look like this:


store.addStoreListener(new StoreListener<BaseModelData>() {

@Override
public void storeDataChanged(StoreEvent<BaseModelData> se) {
ListStore<BaseModelData> eventStore = (ListStore<BaseModelData>) se.getStore();
List<BaseModelData> models = eventStore.getModels();
for (BaseModelData baseModelData : models) {
baseModelData.set("name", "xxx");
}
}
});



for example if you count something:


store.addStoreListener(new StoreListener<BaseModelData>() {

@Override
public void storeDataChanged(StoreEvent<BaseModelData> se) {
ListStore<BaseModelData> eventStore = (ListStore<BaseModelData>) se.getStore();
List<BaseModelData> models = eventStore.getModels();
int i = 0;
for (BaseModelData baseModelData : models) {
i++; // <--- calculate here
baseModelData.set("counter", i);
}
}
});

fother
1 Sep 2009, 11:37 AM
No, also i dont see a good point for this. In a Grid you can define a custom cell renderer for each cell. With that you can format your data.

a good point can be..

negative appears red
positive appears blue..

?

lmivan
1 Sep 2009, 2:12 PM
...

for example if you count something:


store.addStoreListener(new StoreListener<BaseModelData>() {

@Override
public void storeDataChanged(StoreEvent<BaseModelData> se) {
ListStore<BaseModelData> eventStore = (ListStore<BaseModelData>) se.getStore();
List<BaseModelData> models = eventStore.getModels();
int i = 0;
for (BaseModelData baseModelData : models) {
i++; // <--- calculate here
baseModelData.set("counter", i);
}
}
});

Thank you very very much Arno.Nyhm for your help. I really appreciate it. I didn't know that it was possible to set a new field in my model without defining it. I've been reading and trying some examples without a "real" domain, only a domain for the grid. I didn't know that it was possible to mix real domain fields (that are saved into the database) with "ficticious" fields that are only used to display some data.

Here is the solution:


// Total
column = new ColumnConfig();
column.setId("accumulatedAmount"); // Ficticious field, not in my real model
column.setHeader(constants.total());
column.setWidth(80);
columns.add(column);

store.addStoreListener(new StoreListener<BeanModel>() {

double totalRow = 0.0;

@SuppressWarnings("unchecked")
public void storeDataChanged(StoreEvent<BeanModel> se) {
ListStore<BeanModel> eventStore = (ListStore<BeanModel>) se.getStore();
List<BeanModel> models = eventStore.getModels();

for (BaseModelData baseModelData : models) {
double tranAmount = baseModelData.get("transactionAmount");

totalRow += tranAmount;
String style = totalRow < 0 ? "red" : "green";
String accumulatedAmount = "<span style='color:" + style + "'>" + MuflyUtils.numberFormater.format(totalRow) + "</span>";

baseModelData.set("accumulatedAmount", accumulatedAmount);
}
}
});
Thanks again a lot. I've been looking for a guide or getting started with GXT 2.0 but I haven't found something and it is hard to figure it out how it works and all its possibilities.

Regards, Iván.

lmivan
1 Sep 2009, 2:13 PM
a good point can be..

negative appears red
positive appears blue..

?

As you can see in my previous message I'm using red for negatives and green for positives...

Regards, Iván.