Add filters to LiveGrid? - gwt

I am using gxt's LiveGrid. I want to add filters. I have added below few lines but data is not filtered. Am I missing any thing here?
GridFilters filters = new GridFilters();
filters.setLocal(true);
StringFilter nameFilter = new StringFilter("column name");
filters.addFilter(nameFilter);
filters.init(liveGrid);
liveGrid.addPlugin(filters);

From the filter javadoc :
To add a filter to a Grid column, create an instance of a concrete subclass of Filter, passing to the constructor the ValueProvider for the column, then add the filter to a GridFilters
Your code sample seems too restrinct and should probably be parameterized. The StringFilter should be given a ValueProvider for the property of the model object you wish to filter. Following is a simple overview of how to create a Grid with Filters.
Let's say you have a class User
public class User implements Serializable {
private String name;
private Integer id;
// Setters and getters
}
public interface UserProperties extends PropertyAccess<User> {
#Path("id")
ModelKeyProvider<User> key();
ValueProvider<User, String> name();
}
To create a grid that will display your users, you would do as follow
private static final UserProperties props = GWT.create(UserProperties.class);
...
// Create column config
ColumnConfig<User, String> nameCol = new ColumnConfig<User, String>(props.name(), 200, "Name");
// Create column model
List<ColumnConfig<User, ?>> l = new ArrayList<ColumnConfig<User, ?>>();
l.add(nameCol);
ColumnModel<User> cm = new ColumnModel<User>(l);
// Create User store
ListStore<User> store = new ListStore<User>(props.key());
// Create your grid
final LiveGridView<User> liveGridView = new LiveGridView<User>();
liveGridView.setForceFit(true);
Grid<User> view = new Grid<User>(store, cm) {
#Override
protected void onAfterFirstAttach() {
super.onAfterFirstAttach();
// Get grid data
}
};
// Create a String filter for the column
StringFilter<User> nameFilter = new StringFilter<User>(props.name());
// Create a GridFilters
GridFilters<User> filters = new GridFilters<User>();
filters.initPlugin(grid);
filters.setLocal(true);
filters.addFilter(nameFilter);

GridFilters filters = new GridFilters();
filters.setLocal(true);
StringFilter nameFilter = new StringFilter("column name");
filters.addFilter(nameFilter);
filters.init(liveGrid);
liveGrid.addPlugin(filters);
If u want to get the data after filter applied u need to overide reload() method of AbstractGridFilters.

Related

unit-testing Wicket input components

I just wrote my first Wicket component :) It contains a ListView with some Radio input fields. Now I want to unit test if a selected value makes its way to the model.
As WicketTester.newFormTester("myForm") expects a form, I try to create a form on the fly:
public void testDataBinding()
{
Model model = ...
MyRadioComponent myRadioComponent = new MyRadioComponent (...);
Form form = new Form("myForm", ...);
form.add(myRadioComponent);
WicketTester wicketTester = new WicketTester();
wicketTester.startComponentInPage(form);
// FormTester formTester = wicketTester.newFormTester("myForm");
// ...
}
Now wicketTester.startComponentInPage(form) results in:
Failed: Component [myForm] (path = [0:x]) must be applied to a tag of type [form],
not: '<span wicket:id="myForm" id="myForm3">'
Any idea how to fix this and/or how to test such an input component the right way?
OK, in detail the solution now looks like this:
public FormTester createFormTester(Component c) {
final WicketTester wicketTester = new WicketTester();
final FormPage page = new FormPage(c);
wicketTester.startPage(page);
return wicketTester.newFormTester(page.getPathToForm());
}
private static class FormPage extends WebPage implements IMarkupResourceStreamProvider {
private final Form<Void> form;
private final Component c;
private FormPage(final Component c) {
this.c = c;
add(form = new Form<>("form"));
form.add(c);
}
public String getPathToForm() {
return form.getPageRelativePath();
}
#Override
public IResourceStream getMarkupResourceStream(MarkupContainer container, Class<?> containerClass) {
return new StringResourceStream(
"<html><body>"
+ "<form wicket:id='" + form.getId() + "'><span wicket:id='" + c.getId() + "'/></form>"
+ "</body></html>");
}
}
I believe startComponentInPage uses a <span> for its component. Wicket checks that Forms are attached to <form> tags which is why you get this error.
You need to create your own test page with a <form> inside it. See org.apache.wicket.markup.html.form.NumberTextFieldTest for an example of inline markup. Otherwise, create a Form test page class with associated html markup file.

In GWT 2.5, how do I populate multiple parts of a cell based up AbstractCell

I have a class ContactCell based on AbstractCell.
It has two Labels and one Image (defined in GWT 2.5's UiBinder).
How do I Column.addColumn() to add a this custom cell to a CellTable?
And If so, how do I use the method getValue() to populate the fields of ContactCell when getValue() only returns simple values (such as String).
Column<Contact, String> column = new Column<Contact, String>(
new ContactCell()) {
#Override
public String getValue(Contact object) {
return object... CAN ONLY RETURN ONE VALUE. HOW TO POPULATE 2 LABELS & IMAGE?
}
};
You can change the render string by overridding the onrender mathod of the cell as follows.
Assuming 2 labels and a image can be computed from the value returned by getValue mathod.
ContactCell contactCell = new ContactCell()
{
#Override
public void render( com.google.gwt.cell.client.Cell.Context context, SafeHtml value, SafeHtmlBuilder sb )
{
// do value check and compute label1 and label2 and calso compute the image path.
sb.appendHtmlConstant( "<label>LABEL1</label>" +"<label>LABEL2</label>"+"<image></image>" )
}
});
Column<Contact, String> column = new Column<Contact, String>( contactCell )
{
#Override
public String getValue(Contact object)
{
return object... CAN ONLY RETURN ONE VALUE. HOW TO POPULATE 2 LABELS & IMAGE?
}
};
You can either use an IdentityColumn instead of a normal Column (will pass through the entire Contact object) or you use a normal Column like this:
Column<Contact, String[]> column = new Column<Contact, String[]>(
new ContactCell()) {
#Override
public String[] getValue(Contact object) {
String[] retvalue = new String[2];
retvalue[0] = "SOMETHING";
retvalue[1] = "SOME OTHER THING";
return retvalue;
}
};
If the cell based on AbstractCell is defined using UiBinder then it's not currently (GWT 2.5) possible to add such cells to a CellTable.

GWT CellTable Data Not Displaying

I have the following code in my modules onModuleLoad() method:
List<MyPromo> promotionData = new ArrayList<MyPromo>();
MyPromo promotion1 = new MyPromo(...);
promotionData.add(promotion1);
PromotionTable<MyPromo> promoTable = new PromotionTable<MyPromo>(tableColumns, promotionData);
and
public class PromotionTable <T extends Promotion> extends CellTable<T>{
public PromotionTable(List<ColumnGroup<T>> columns, List<T> data) {
super();
this.setWidth("100%");
this.setHeight("500px");
this.setHeaderBuilder(new PromotionTableHeaderBuilder(columns, this));
this.setFooterBuilder(new PromotionTableFooterBuilder(this));
ListDataProvider<T> dataProvider = new ListDataProvider<T>();
dataProvider.setList(data);
dataProvider.addDataDisplay(this);
}
...
The columns for the CellTable just take properties off the MyPromo object and return a String value to display. However, nothing is displayed in the table, just the column headers. Any idea why this is?
The problem is with the following code
ListDataProvider<T> dataProvider = new ListDataProvider<T>();
dataProvider.setList(data);
dataProvider.addDataDisplay(this);
By the time you do setList, ListDataProvider must know its consumers ie displays (Refer setList implementaion).
So, the order of the code is wrong. First do addDataDisplay and then do setList. It will work.
I was constructing the dataProvider and assigning it to the celltable (or mu extension of) in the constructor. It didn't like this for some reason, when I moved it out it worked.
Here is a simple example of CellTable, SimplePager and ListDataProvider.
CellTable<AlarmDisplayBTO> cellTable= new CellTable<AlarmDisplayBTO>();
TextColumn<AlarmDisplayBTO> dateColumn = new TextColumn<AlarmDisplayBTO>() {
#Override
public String getValue(AlarmDisplayBTO object) {
return object.getDate();
}
};
cellTable.addColumn(dateColumn, "Date");
TextColumn<AlarmDisplayBTO> alarmNameColumn = new TextColumn<AlarmDisplayBTO>() {
#Override
public String getValue(AlarmDisplayBTO object) {
return object.getAlarmName();
}
};
cellTable.addColumn(alarmNameColumn, "Alarm Name");
cellTable.setRowCount(alarmList.size());
// alarmList is an ArrayList<AlarmDisplayBTO> rendered from RPC call
cellTable.setRowData(0, alarmList);
cellTable.setEmptyTableWidget(new Label(" No Records Found"));
ListDataProvider<AlarmDisplayBTO> dataProvider = new ListDataProvider<AlarmDisplayBTO>();
dataProvider.addDataDisplay(cellTable);
dataProvider.setList(alarmList);
SimplePager pager = new SimplePager();
pager.setDisplay(cellTable);
pager.setPageSize(20); // 20 rows will be shown at a time
VerticalPanel vPanel = new VerticalPanel();
vPanel.add(cellTable);
vPanel.add(pager);
setWidget(new ScrollPanel(vPanel));
Hope this may help..

GWT-Editors and sub-editors

I'm trying to run an example of Editors with sub-editors.
When flushing the parent the value of child editor is null.
The classes are Person and Address.
The main editor is:
// editor fields
public TextField firstname;
public TextField lastname;
public NumberField<Integer> id;
public AddressEditor address = new AddressEditor();
public PersonEditor(Person p){
asWidget();
}
#Override
public Widget asWidget() {
setWidth(400);
setBodyStyle("padding: 5px;");
setHeaderVisible(false);
VerticalLayoutContainer c = new VerticalLayoutContainer();
id = new NumberField<Integer>(new IntegerPropertyEditor());
// id.setName("id");
id.setFormat(NumberFormat.getFormat("0.00"));
id.setAllowNegative(false);
c.add(new FieldLabel(id, "id"), new VerticalLayoutData(1, -1));
firstname = new TextField();
// firstname.setName("firstname");
c.add(new FieldLabel(firstname, "firstname"), new VerticalLayoutData(1, -1));
lastname = new TextField();
lastname.setName("lastname");
c.add(new FieldLabel(lastname, "lastname"), new VerticalLayoutData(1, -1));
c.add(address);
add(c);
return this;
The sub-editor:
public class AddressEditor extends Composite implements Editor<Address> {
private AddressProperties props = GWT.create(AddressProperties.class);
private ListStore<Address> store = new ListStore<Address>(props.key());
ComboBox<Address> address;
public AddressEditor() {
for(int i = 0; i < 5; i ++)
store.add(new Address("city" + i));
address = new ComboBox<Address>(store, props.nameLabel());
address.setAllowBlank(false);
address.setForceSelection(true);
address.setTriggerAction(TriggerAction.ALL);
initWidget(address);
}
And this is where the Driver is created:
private HorizontalPanel hp;
private Person googleContact;
PersonDriver driver = GWT.create(PersonDriver.class);
public void onModuleLoad() {
hp = new HorizontalPanel();
hp.setSpacing(10);
googleContact = new Person();
PersonEditor pe = new PersonEditor(googleContact);
driver.initialize(pe);
driver.edit(googleContact);
TextButton save = new TextButton("Save");
save.addSelectHandler(new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
googleContact = driver.flush();
System.out.println(googleContact.getFirstname() + ", " + googleContact.getAddress().getCity());
if (driver.hasErrors()) {
new MessageBox("Please correct the errors before saving.").show();
return;
}
}
});
The value of googleContact.getFirstname() is filled but googleContact.getAddress() is always null.
What I'm missing?
The AddressEditor needs to map to the Address model - presently, it doesn't seem to, unless Address only has one getter/setter, called getAddress() and setAddress(Address), which wouldn't really make a lot of sense.
If you want just a ComboBox<Address> (which implements Editor<Address> already), consider putting that combo in the PersonEditor directly. Otherwise, you'll need to add #Path("") to the AddressEditor.address field, to indicate that it should be directly editing the value itself, and not a sub property (i.e. person.getAddress().getAddress()).
Another way to build an address editor would be to list each of the properties of the Address type in the AddressEditor. This is what the driver is expecting by default, so it is confused when it sees a field called 'address'.
Two quick thoughts on the code itself: there is no need to pass a person into the PersonEditor - thats the job of the driver itself. Second, your editor fields do not need to be public, they just can't be private.

Where does IModel Apache Wicket retrieve an object?

First of all, please take a look at how IModel is used in this example:
#SuppressWarnings("serial")
public static List<IColumn> getTableColumns(
final ReportParams reportParams, final boolean columnsSortable
) {
List<IColumn> columns = new ArrayList<IColumn>();
final Map<String,ToolInfo> eventIdToolMap = Locator.getFacade().getEventRegistryService().getEventIdToolMap();
// site
if(Locator.getFacade().getReportManager().isReportColumnAvailable(reportParams, StatsManager.T_SITE)) {
columns.add(new PropertyColumn(new ResourceModel("th_site"), columnsSortable ? ReportsDataProvider.COL_SITE : null, ReportsDataProvider.COL_SITE) {
#Override
public void populateItem(Item item, String componentId, IModel model) {
final String site = ((Stat) model.getObject()).getSiteId();
String lbl = "", href = "";
Site s = null;
try{
s = Locator.getFacade().getSiteService().getSite(site);
lbl = s.getTitle();
href = s.getUrl();
}catch(IdUnusedException e){
lbl = (String) new ResourceModel("site_unknown").getObject();
href = null;
}
item.add(new ImageWithLink(componentId, null, href, lbl, "_parent"));
}
});
}
And my questions are:
How does populateItem get an input for IModel parameter?
I cannot find any code in this application, which explicitly constructs IModel object. Is it correct for me to assume that the object is retrieved directly from a table in the database? I'm thinking of this because Mapping Hibernate is used for this application.
The models are created using the IDataProvider you provide to the DataTable (DataTable constructor will also take your IColumn List) .
The IDataProvider could use Hibernate - hard to say without having more information on that implementation.