SmartGWT widgets can render themselves sensibly using the data source definition. So for a grid, we don’t need to define the columns explicitly. However, we can override the rendering of some or all columns as needed.
Assume that our data source and data looks like this:
class CompanyDataSource extends DataSource {
public CompanyDataSource(String id) {
setID(id);
DataSourceTextField companyName = new DataSourceTextField("company", "Company");
DataSourceFloatField price = new DataSourceFloatField("price", "Price");
DataSourceDateField lastChanged = new DataSourceDateField("lastChanged", "Last Changed");
setFields(companyName, price, lastChanged);
}
}
"3m Co", "71.72", "9/1 01:25 AM"
And the grid that renders this data
DataSource dataSource = new CompanyDataSource(“companyList1”);
dataSource.setClientOnly(true);
ListGrid companyGrid = new ListGrid();
companyGrid.setHeight(300);
companyGrid.setWidth(500);
companyGrid.setTitle("SmartGWT grid");
companyGrid.setDataSource(dataSource);
companyGrid.setAutoFetchData(true);
To override the display format of lastChanged column, one approach would be
ListGridField lastChangedField = new ListGridField("lastChanged", "Last Changed (new title)", 180);
CellFormatter dateFormatter = new CellFormatter(){
public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
DateTimeFormat inputFormat = DateTimeFormat.getFormat("d/M hh:mm a");
DateTimeFormat outputFormat = DateTimeFormat.getFormat("MMM dd HH 'hours' mm 'minutes'");
Date inputDate = inputFormat.parse(value.toString());
String output = outputFormat.format(inputDate);
return output;
}
};
lastChangedField.setCellFormatter(dateFormatter);
companyGrid.setFields(lastChangedField);
We define a ListGridField with the same name “lastChanged” as in the data source. SmartGWT will use this name to do the merge. Our custom cell formatter matches the input date format and returns it in a different format.
But now the grid will only display this field. To cause it to display other data source fields as they are, we need to call
companyGrid.setUseAllDataSourceFields(true);
We can also override the date format in the data source itself so that all widgets sourcing this data will reflect it. As I was thinking about this, I came across this post on the SmartGWT forums. The API will support this functionality soon and as that thread also mentions, for formatting dates, you can use ListGrid.setDateFormatter() and DateItem.setDisplayFormat().
Thats it for this time. Ill keep posting tidbits as I learn along the way.
GWT-Ext Store instances are all over my code. And I am populating them by various means. While migrating from GWT-Ext to SmartGWT, converting Stores to DataSources will probably take up a lot of time. I was wondering if I could migrate and test only the grids first and deal with the stores later. Code below could help do just that. It creates a DataSource from a Store. You can use this data source to populate SmartGWT grids and when the grids are working fine, replace the stores completely. Isn’t exactly a life saver but nevertheless. Have tested it only on a trivial store.
It doesn’t matter but assume that the RecordDef used to create the Store looks like this:
RecordDef recordDef = new RecordDef(new FieldDef[] {
new StringFieldDef("company"),
new FloatFieldDef("price"),
new FloatFieldDef("change"),
new FloatFieldDef("pctChange"),
new DateFieldDef("lastChanged", "n/j h:ia"),
new StringFieldDef("symbol"),
new StringFieldDef("industry")
});
Create a DataSource with the same fields:
private DataSource createDataSource(Store store){
DataSource dataSource = new DataSource();
dataSource.setClientOnly(true);
String[] fields = store.getFields();
for(String field:fields) {
DataSourceField smartgwtField = new DataSourceField();
smartgwtField.setName(field);
dataSource.addField(smartgwtField);
}
return dataSource;
}
Add a method that copies records from the Store to the data source created above and call it in the Store’s onLoad handler
public void copyStore(Store store, DataSource dataSource) {
Record[] records = store.getRecords();
String[] fields = store.getFields();
for(Record gwtextRecord:records) {
ListGridRecord smartgwtRecord = new ListGridRecord();
for(String field:fields) {
smartgwtRecord.setAttribute(field, gwtextRecord.getAsString(field));
}
dataSource.addData(smartgwtRecord);
}
}
For heavy stores, this code will probably punish the browser and column data types are ignored as well but it is meant only for the dev environment until all components have been replaced eventually.
PS: If you need it, here is a small sample with GWT-Ext and SmartGWT grids being populated from the same RPC method. You will need to add gwtext.jar and smartgwt.jar and use Cypal studio plugin or add compile/run scripts.
SmartGWT 1.0, a web application library based on SmartClient and GWT, was released this Monday. From the release announcement at Sanjiv’s blog and the showcase demos, it is evident that this library packs a lot of power and is definitely worth checking out. I have come across SmartClient only recently. And now that I know of it, Ill try and get acquainted with it when I can.
Links:
SmartClient: http://www.smartclient.com/
SmartGWT: http://code.google.com/p/smartgwt/
Visual Builder videos: http://www.smartclient.com/technology/visualbuilder.jsp