Sortable ListView in Apache WIcket - wicket

I have successfully displayed data in tabular form using ListView. However, I wanted it to be sortable. How do I go about doing this?

Hmm.. Perhaps DefaultDataTable could have been better suited for your use case of displaying tabular data in a sortable fashion. Let me know if you need more explanation or a code example.

You can just sort the List that you pass to ListView.
Something like:
final SortState sort = SortState.ByName;
add(new ListView(id, new AbstractReadOnlyModel<ArrayList<Person>>() {
public ArrayList<Person> getObject() {
ArrayList<Person> list = makeList();
Comparator<Person> comparator = getComparator(sort);
Collections.sort(comparator, list);
return list;
}
});
add(new Link(sortByAgeLinkId) {
public void onClick() { sort = SortState.ByAge;}
});
... more links for different criteria.

Related

GWT Sorting after filtering a table

I have a simple table (CellTable) and a TextBox for filter.
Values for CellTable I take from backend. After list of items is loaded I can put some filter string to get suitable result. To filter list from dataprovider I use a predicate. After filtering I set result to CellTable.
Like here:
void onFilterNameKeyUp(KeyUpEvent e) {
List<CustomerDTO> filtered = this.dataProvider.getList();
Predicate<CustomerDTO> filter = new Predicate<CustomerDTO>() {
#Override
public boolean apply(CustomerDTO input) {
if (input.getName() == null) {
return false;
} else {
return input.getName().toLowerCase()
.contains(filterName.getValue().toLowerCase());
}
}
};
filtered = Lists.newArrayList(Iterables.filter(this.dataProvider.getList(), filter));
this.customerList.setRowCount(filtered.size(), true);
this.customerList.setRowData(0, filtered);
}
this.dataProvider = new ListDataProvider<CustomerDTO>();
dataProvider.addDataDisplay(this.customerList);
final ListHandler<CustomerDTO> sortHandler = new ListHandler<CustomerDTO>(
this.dataProvider.getList());
this.customerList.addColumnSortHandler(sortHandler);
this.customerList.getColumnSortList().push(this.rbKeyNameColumn);
Everything work fine but I have also a sort handler for first column of this table and when I want to sort a list then I'm sorting original list of items.
How to solve this problem? It means that I want to sort and display filtered list instead of original list from dataprovider.
Please help.
I have a table changing content after receiving some data from the server. This is my approach:
public void onSuccess(List<List<String>> result) {
List<Product> list = dataProvider.getList();
list.clear();
r_tableproducts.setRowCount(result.size());
for (List<String> l : result) {
list.add(new Product(l));
}
r_tableproducts.getColumnSortList().clear();
r_tableproducts.getColumnSortList().push(r_tableproducts.getColumn(1));
ColumnSortEvent.fire(r_tableproducts,r_tableproducts.getColumnSortList());
}
This sorts my list using 2nd column after reciving new data (overriding all old data).
Maybe try this approach? Filter your data in a new list and modify the list your dataProvider provides you, adding all elements.
Something like:
List<CustomerDTO> result = Lists.newArrayList(Iterables.filter(this.dataProvider.getList(), filter));
this.customerList.setRowCount(result.size(), true);
this.dataProvider.getList().clear();
this.dataProvider.getList().addAll(result);
You need to separate the dataProvider that holds the full list and provide a separate "filtered" data provider that will be driving the display of the cellTable. The cellTable in below example is bound to a filteredDataProvider for sorting, display purposes.
The code below is to give a general idea and therefore may not be syntactically accurate.
void onFilterNameKeyUp(KeyUpEvent e) {
List<CustomerDTO> filtered = this.dataProvider.getList();
Predicate<CustomerDTO> filter = new Predicate<CustomerDTO>() {
#Override
public boolean apply(CustomerDTO input) {
if (input.getName() == null) {
return false;
} else {
return input.getName().toLowerCase()
.contains(filterName.getValue().toLowerCase());
}
}
};
filtered = Lists.newArrayList(Iterables.filter(this.dataProvider.getList(), filter));
this.customerList.setRowCount(filtered.size(), true);
this.filteredDataProvider.getList().clear();
this.filteredDataProvider.getList().addAll(filtered);
}
this.dataProvider = new ListDataProvider<CustomerDTO>();
// Code here to populate the dataProvider
this.filteredDataProvider = new ListDataProvider<CustomerDTO>();
// Creating separate DataProvider to hold the filtered set
this.filteredDataProvider.getList().addAll(this.dataProvider.getList());
filteredDataProvider.addDataDisplay(this.customerList);
// dataProvider.addDataDisplay(this.customerList);
// Sort Handler uses filteredDataProvider instead of the dataProvider with full list
final ListHandler<CustomerDTO> sortHandler = new ListHandler<CustomerDTO>(
this.filteredDataProvider.getList());
this.customerList.addColumnSortHandler(sortHandler);
this.customerList.getColumnSortList().push(this.rbKeyNameColumn);

How to delete an item from list view without iterating

I have a an ArrayList<Color> colorList for my list view with an ArrayAdapter. My POJO like this:
public class Color {
int id;
String name;
//getter setter
}
Everything is fetched from the server. so the id of each color object will match an id in the DB table.
In my ArrayAdapter's getView I am setting the tag with an id from the database.
holder.imageButton.setTag(item.getId()); //color id from database
holder.imageButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int id = (Integer) v.getTag();
new DeleteColor(id).execute();
}
});
In the above code I am sending the clicked item's id to the server for deletion
What is the easy way to remove an item from my listView?
What I'm doing right now is:
class DeleteColor extends AsyncTask<String, String, String> {
int id;
public DeleteColor (int id) {
this.id = id;
}
#Override
protected String doInBackground (String ... args) {
MyManager.INSTANCE.getService().deleteColor(id, new Callback<Integer>() {
#Override
public void success(Integer id, Response response) {
//loop through the colorlist to find which one to remove
for (int i = 0; i < colorList.size(); i++) {
Color c = colorList.get(i);
if (c.getId() == id) {
colorList.remove(c);
adapter.notifyDataSetChanged();
break;
}
}
}
#Override
public void failure(RetrofitError retrofitError) {
}
});
return "";
}
}
As you can see, I am looping through the entire colorList to find out the one that has the id I want removed and then removing it. Is this a good approach to achieve this?
Question
How can I avoid looping through the entire colorList to find the one that needs to be deleted.
You have the id of the object you want to remove from the list.
Use that id to get the object, then use the ArrayList method indexOf(Object object) to find the index of the object in your list and remove it.
There technically is no way to directly access an item in a list.
In school we built a list in Java ourselves and it consisted of different entries that were connected one to another. But the first only was connected to the second and that in turn only to the third. So you couldn't even access the object on the second place, without beginning at the top. To access anything you had to iterate the list.
I just read Sound Conception's answer and I'm pretty sure that the indexOf(Object)-method itself iterates through the whole list (unless the Java developers did some magic, which actually could be. ;) I'm not a professional and haven't looked into the code of that method). But your manual looping probably is the most efficient way.
I don't think, there is a practical difference in execution time. So you might want to use Sound Conception's method to keep the code simple. It's totally up to you!
There is one another way if you set the item position as tag on your view.....
Then v.getId() will give you the position clicked and that you can directly remove from your list as arraylist.remove(positionclicked);

GWT DataGrid header click event for sorting

I want to know if user clicked on header for Ascending or Descending sorting.
How can I find that?
Regards
Try this:
1) create SortHandler and attach to your grid
ColumnSortEvent.AsyncHandler sortHandler= new ColumnSortEvent.AsyncHandler(grid);
grid.addColumnSortHandler(sortHandler);
ColumnSortList columnSortList = grid.getColumnSortList();
2) create your Column (TextColumn etc) such as:
TextColumn<Dog> yourTextColumn = new TextColumn<Dog>() {
#Override
public String getValue(String object) {
return object;
}
}
3) create your Header
Header yourHeader = new Header() {
#Override
public Object getValue() {
return value; // here return header value
}
}
3) add column to grid and push a ColumnSortInfo onto the list
grid.addColumn(yourTextColumn, yourHeader);
columnSortList.push(new ColumnSortList.ColumnSortInfo(yourColumn, true));
You can always look here for more useful examples.
in order to get the direction of the ordering, all you have to do is to get the ColumnSortList and call method #get(0) with zero index. as documentation of ColumnSortList says the "The 0th item is the {#link ColumnSortInfo} of the most recently sorted * column.". so the returned object (which is ColumnSortList.ColumnSortInfo) contains information about last clicked Column and it has a method called #isAscending() which is a flag to identify the direction.
the sample code:
ColumnSortList sortList = dataGrid.getColumnSortList();
ColumnSortList.ColumnSortInfo info = sortList.get(0);
also want to note that this code block should be in AsyncDataProvider#onRangeChanged.
there is also an alternative to this, consider the following:
columnSortHandler = new ColumnSortEvent.AsyncHandler(table) {
#Override
public void onColumnSort(ColumnSortEvent event) {
List<T> newData = new ArrayList(table.getVisibleItems());
if (event.isSortAscending()) {
Collections.sort(newData, (Comparator)event.getColumn());
} else {
Collections.sort(newData, (Comparator)event.getColumn());
Collections.reverse(newData);
}
table.setRowData(newData);
}
};
table.addColumnSortHandler(columnSortHandler);

Adding style to a ButtonCell

I know my question is considered initially to refer to the "very novice" level, but I have spent quite o lot of time on searching for the answer. I have used in a gwt application a DataGrid and I have attached a diversity of specific Cell widgets (i.e. TextCell, ButtonCell). My concern is how I can add and handle styling to the button of a ButtonCell through custom css. The code which implements the column of ButtonCells looks like as follows:
Column<FilterInfo, String> delButtonColumn = new Column<FilterInfo, String>(new ButtonCell()) {
#Override
public String getValue(FilterInfo object) {
return "X";
}
};
So, how can I add styling to the button (not to the entire Cell)? I suspect that I should also override the render function, however I cannot figure out how the styling is applied
#Override
public void render(Context context, FilterInfo object, SafeHtmlBuilder sb) {
super.render(context, object, sb);
???
}
You can use the setCellStyleNames() method in Column to apply a style that will be applied to every cell of the column. You have to use GWT 2.4 for this to work. It will probably be something like that. Please note that the code was written outside of any IDE, so it may contain errors.
Column<FilterInfo, String> delButtonColumn = new Column<FilterInfo, String>(new ButtonCell()) {
#Override
public String getValue(FilterInfo object) {
return "X";
}
};
delButtonColumn.setCelLStyleNames("yourStyleName");
And the css :
.yourStyleName.gwt-Button{
//your styling here
}

GWT:selection model not working properly

I have a celltable in GWT which have checkboxes, to select multiple checkboxes i am using selectionModel,once I check any checkbox its values get saved in the selectionModel,but then when i uncheck the checkbox , they never get remove , i want to remove the previous selection , how can it be possible
below is the code
List<Categories> selected;
display.getListWidget().getSelectionModel().addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
selected = new ArrayList<Categories>(
((MultiSelectionModel<Categories>) display.getListWidget().getSelectionModel()).getSelectedSet());
}
});
What i am trying to do is
display.getListWidget().getSelectionModel().setSelected(categories, false);
but its not working , coz i guess categories is not the one which is already added ..
Any Suggestions
Thanks
If you could clarify your question with some more code or by being more specific, we might be able to give a better answer. From your question, I'm guessing that your Categories equals and hashcode are not overwritten in a way that the "categories" you are trying to set is being found.
I'm guessing a bit here but I think a KeyProvider will help you deselect the correct Categories object.
view:
SelectionModel<Categories> selectionModel;
ProvidesKey<Categories> keyProvider = new ProvidesKey<Categories>() {
public Object getKey(Categories categories) {
return item == null ? null : categories.id() // or some unique identifier
}
};
CellTable cellTable = new CellTable<Categories>(keyProvider);
// Omitted..Add columns..
selectionModel = new MultiSelectionModel<Categories>(keyProvider);
cellTable.setSelectionModel(selectionModel);
presenter:
List<Categories> selected;
display.getListWidget().getSelectionMode().addSelectionChangeHandler(
new SelectionChangeHandler() {
public void onSelectionChange() {
MultiSelectionModel selectionModel =
(MultiSelectionModel) display.getListWidget().getSelectionModel();
selected = Lists.newArrayList(selectionModel.getSelectedSet());
}
});