Wicket provides the much reusable components to achieve the website feasibility. By overriding the existing components we can create our own components as per our need.
Editable grid with sorting, filtering and pagination has been developed by extending few classes which already exist in wicket framework.
I wish to develop the component which will support the following features:
1. The component should list all the dates regardless of the list of objects I passed. Component should accept generic data.
2. It should provide the option for sorting by clicking the header of the table.
3. It should provide the filtering option to find the specific data.
4. Each row can be editable by default and should be able to delete
5. And then pagination.
Simply it should looks like the following one….
First SubmitButtonPanel.jave has been created which is used for the header, it will provide the header link for the user to obtain the sorted data
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitButton;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.list.PageableListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
public class SubmitButtonPanel<T extends AbstractEntity> extends Panel{
/**
*
*/
private static final long serialVersionUID = 1L;
AjaxSubmitButton submitLink;
Label label;
PageableListView<T> pageableListView;
boolean isClicked=false;
public SubmitButtonPanel(String id,PageableListView<T> listView,String resourceKey,String expression) {
super(id);
pageableListView=listView;
add(newSubmitButton(listView,resourceKey,expression));
}
protected AjaxButton newSubmitButton(PageableListView<T> listView,String resourceKey,final String expression) {
AjaxButton submitLink=new AjaxButton("submitLink",new ResourceModel(resourceKey)) {
@Override
public void onSubmit() {
if(isClicked){
isClicked=false;
}else{
isClicked=true;
}
onClick(isClicked);
}
@Override
protected void onSubmit(AjaxRequestTarget arg0, Form<?> arg1) {
}
};
submitLink.setLabel(Model.of("Name"));
return submitLink;
}
protected void newLabel(AjaxSubmitButton ajaxSubmitLink,String resourceKey){
label=new Label("label",new ResourceModel(resourceKey));
ajaxSubmitLink.add(label);
}
protected void onClick(boolean isSorting){
}
}
The Html file this panel is SubmitButtonPanel.html :
<wicket:panel>
<style type="text/css">
.submitLink {
background-color: transparent;
text-decoration: underline;
border: none;
cursor: pointer;
cursor: hand;
}
</style>
<input type="submit" wicket:id="submitLink" class="submitLink"/>
</wicket:panel>
The css provided in that panel will help to display the button as link.
The pageableList.java was developed to implement all the requirements
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigator;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.PageableListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
public abstract class PageableList<T extends AbstractEntity> extends Panel {
/**
*
*/
TextField textField;
List<T> list = null;
T modelObject = null;
private static final long serialVersionUID = 1L;
PageableListView<T> listView;
AjaxPagingNavigator ajaxPagingNavigator;
WebMarkupContainer datacontainer;
TableColumn tableHeader;
TableColumn fileterColumn;
Label label;
Form form;
public PageableList(String id, List<T> pageablelist, final T t) {
super(id);
this.list = pageablelist;
modelObject = t;
form = new Form("pageableForm");
datacontainer = new WebMarkupContainer("data");
datacontainer.setOutputMarkupId(true);
datacontainer.setOutputMarkupPlaceholderTag(true);
final List<T> pageList = new ArrayList<T>(list);
final IModel<List<T>> iModels = new LoadableDetachableModel<List<T>>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected List<T> load() {
return pageList;
}
};
IModel<T> iModel = new LoadableDetachableModel<T>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected T load() {
return t;
}
};
listView = getPageableList(pageList);
listView.setOutputMarkupId(true);
listView.setReuseItems(true);
listView.setOutputMarkupPlaceholderTag(true);
datacontainer.add(listView);
ajaxPagingNavigator = new AjaxPagingNavigator("navigator", listView);
ajaxPagingNavigator.setOutputMarkupId(true);
ajaxPagingNavigator.setOutputMarkupPlaceholderTag(true);
datacontainer.add(ajaxPagingNavigator);
form.add(new AjaxButton("search") {
@Override
public void onSubmit() {
List<T> filteredList = new ArrayList<T>();
Iterator<T> iterator = pageList.iterator();
while (iterator.hasNext()) {
T model = iterator.next();
if (filterCondition(modelObject, model)) {
filteredList.add(model);
}
}
datacontainer.remove(listView);
datacontainer.remove(ajaxPagingNavigator);
listView = getPageableList(filteredList);
listView.setOutputMarkupId(true);
listView.setReuseItems(true);
listView.setOutputMarkupPlaceholderTag(true);
datacontainer.add(listView);
ajaxPagingNavigator = new AjaxPagingNavigator("navigator",
listView);
datacontainer.add(ajaxPagingNavigator);
form.remove(fileterColumn);
fileterColumn = new TableColumn("filterTool");
fileterColumn.setOutputMarkupId(true);
modelObject = clear();;
addFilterComponent(fileterColumn, listView, modelObject);
form.add(tableHeader);
form.add(fileterColumn);
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
}
});
form.add(new AjaxButton("clear") {
@Override
public void onSubmit() {
List<T> list1 = pageList;
datacontainer.remove(listView);
datacontainer.remove(ajaxPagingNavigator);
listView = getPageableList(list1);
listView.setOutputMarkupId(true);
listView.setReuseItems(true);
listView.setOutputMarkupPlaceholderTag(true);
datacontainer.add(listView);
ajaxPagingNavigator = new AjaxPagingNavigator("navigator",
listView);
datacontainer.add(ajaxPagingNavigator);
form.remove(fileterColumn);
fileterColumn = new TableColumn("filterTool");
fileterColumn.setOutputMarkupId(true);
modelObject = clear();
addFilterComponent(fileterColumn, listView, modelObject);
form.add(tableHeader);
form.add(fileterColumn);
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
listView.setList(iModels.getObject());
form.remove(tableHeader);
form.remove(fileterColumn);
tableHeader = new TableColumn("repeatingHeader");
tableHeader.setOutputMarkupId(true);
fileterColumn = new TableColumn("filterTool");
fileterColumn.setOutputMarkupId(true);
clear();
addFormComponent(tableHeader, listView, modelObject);
form.add(tableHeader);
form.add(fileterColumn);
target.addComponent(form);
}
});
tableHeader = new TableColumn("repeatingHeader");
tableHeader.setOutputMarkupId(true);
fileterColumn = new TableColumn("filterTool");
fileterColumn.setOutputMarkupId(true);
addFilterComponent(fileterColumn, listView, modelObject);
addFormComponent(tableHeader, listView, modelObject);
form.add(tableHeader);
form.add(fileterColumn);
form.add(datacontainer);
form.add(new AjaxButton("Save",new ResourceModel("save")) {
@Override
public void onSubmit() {
System.out.println("Save");
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
}
});
add(form);
}
protected T clear() {
return modelObject;
}
protected void addTableColumns(TableColumn tableColumn, T t) {
}
protected void addFormComponent(TableColumn tableHeader,
PageableListView<T> listView, T modelObject) {
}
protected void addFilterComponent(TableColumn fileterColumn,
PageableListView<T> listView, T modelObject) {
}
protected void addFilterColumn(TableColumn fileterColumn1,
PageableListView<T> LislistView, T t, final String resourceKey,
final String inExpression) {
fileterColumn1.add(new TextPanel(fileterColumn.newChildId(),
new PropertyModel<T>(t, inExpression)));
}
protected void addHeader(TableColumn tableHeader1,
PageableListView<T> LislistView, T t, final String resourceKey,
final String inExpression) {
tableHeader1.add(new SubmitButtonPanel<T>(fileterColumn.newChildId(),
listView, resourceKey, inExpression) {
@Override
protected void onClick(boolean isSorting) {
List<T> list1 = listView.getModelObject();
Collections.sort(list1, new BeanComparator(inExpression));
if (!isSorting) {
Collections.reverse(list1);
}
datacontainer.remove(listView);
datacontainer.remove(ajaxPagingNavigator);
listView = getPageableList(list1);
listView.setOutputMarkupId(true);
listView.setReuseItems(true);
listView.setOutputMarkupPlaceholderTag(true);
datacontainer.add(listView);
ajaxPagingNavigator = new AjaxPagingNavigator("navigator",
listView);
datacontainer.add(ajaxPagingNavigator);
form.remove(fileterColumn);
fileterColumn = new TableColumn("filterTool");
fileterColumn.setOutputMarkupId(true);
addFilterComponent(fileterColumn, listView, modelObject);
form.add(fileterColumn);
}
});
}
protected void addColumn(TableColumn tableColumn, T t,
final String inExpression) {
tableColumn.add(new TextPanel(tableColumn.newChildId(),
new PropertyModel<T>(t, inExpression)));
}
private class TextPanel extends Panel {
public TextPanel(String id, PropertyModel<T> textModel) {
super(id);
add(newTextBox("text", textModel));
}
}
protected TextField newTextBox(String id, PropertyModel<T> textModel) {
textField = new TextField(id, textModel);
textField.setOutputMarkupId(true);
textField.setEnabled(isEnable());
return textField;
}
protected boolean isEnable() {
return true;
}
private class LabelPanel extends Panel {
public LabelPanel(String id, PropertyModel<T> textModel) {
super(id);
add(newLabelBox("label", textModel));
}
}
protected Label newLabelBox(String id, PropertyModel<T> textModel) {
label = new Label(id, textModel);
label.setOutputMarkupId(true);
label.setEnabled(isEnable());
return label;
}
protected boolean filterCondition(T filterObject, T modelObject) {
return false;
}
private PageableListView<T> getPageableList(List<T> pageList) {
PageableListView<T> listView = new PageableListView<T>("rows",
pageList, 4) {
@Override
protected void populateItem(ListItem<T> listItem) {
TableColumn tableColumn = new TableColumn("repeatingView");
tableColumn.setOutputMarkupId(true);
addTableColumns(tableColumn,listItem.getModelObject());
listItem.add(tableColumn);
listItem.add(new AjaxButton("delete", new ResourceModel("delete")) {
@Override
public void onSubmit() {
System.out.println("delete to do");
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
}
});
}
};
return listView;
}
}
AbstractEntity is a super class for all your entity classes.
TableColumn.java is child class of RepeatingView :
public class TableColumn extends RepeatingView{
/**
*
*/
private static final long serialVersionUID = 1L;
public TableColumn(String id) {
super(id);
setOutputMarkupId(true);
}
}
We have two html files for PageableList.java
1. PageableList$TextPanel.html
<wicket:panel>
<input wicket:id="text" type="text" />
</wicket:panel>
2. PageableList$LabelPanel.html
<wicket:panel>
<input wicket:id="text" type="text" />
</wicket:panel>
Create an entity class which extend the abstract entity :
public class AbstractEntity implements Serializable {
}
public class ComponentEntity extends AbstractEntity {
private String empId;
private String name;
private Integer salary;
private boolean isRequired;
public boolean isRequired() {
return isRequired;
}
public void setRequired(boolean isRequired) {
this.isRequired = isRequired;
}
public ComponentEntity(String empId, String name, Integer salary) {
super();
this.empId = empId;
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSalary() {
return salary;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
public ComponentEntity() {
super();
}
}
TestFormPanel.jave is the main class which will override the methods in the pageableList and provide the columns need to be displayed in the grid and filter condition.
import org.apache.wicket.markup.html.list.PageableListView;
public class TestFormPanel extends PageableList<ComponentEntity>{
public TestFormPanel(String id,List<ComponentEntity> list,ComponentEntity componentEntity) {
super(id,list,componentEntity);
setOutputMarkupId(true);
}
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected void addTableColumns(TableColumn tableColumn, ComponentEntity t) {
addColumn(tableColumn, t, "empId");
addColumn(tableColumn, t, "name");
addColumn(tableColumn, t, "salary");
}
@Override
protected void addFilterComponent(TableColumn fileterColumn,
PageableListView<ComponentEntity> listView,
ComponentEntity modelObject) {
addFilterColumn(fileterColumn,listView,modelObject,"SortingPanel.empId","empId");
addFilterColumn(fileterColumn,listView,modelObject,"SortingPanel.name","name");
addFilterColumn(fileterColumn,listView,modelObject,"SortingPanel.salary","salary");
}
@Override
protected void addFormComponent(TableColumn tableHeader,
PageableListView<ComponentEntity> listView,
ComponentEntity modelObject) {
addHeader(tableHeader,listView,modelObject,"SortingPanel.empId",
"empId");
addHeader(tableHeader,listView,modelObject,"SortingPanel.name",
"name");
addHeader(tableHeader,listView,modelObject,"SortingPanel.salary","salary");
}
@Override
protected boolean filterCondition(ComponentEntity filterObject,
ComponentEntity modelObject) {
return
(filterObject.getEmpId()== null || modelObject.getEmpId().equalsIgnoreCase(filterObject.getEmpId())) &&
(filterObject.getSalary() == null || filterObject.getSalary()==modelObject.getSalary()) &&
(filterObject.getName() == null || modelObject.getName().equalsIgnoreCase(filterObject.getName()));
}
@Override
protected ComponentEntity clear() {
return new ComponentEntity();
}
}
TestFormPanel.html :
<wicket:panel>
<form action="" wicket:id="pageableForm">
<table>
<thead>
<tr>
<th wicket:id="repeatingHeader"></th>
</tr>
</thead>
<tbody >
<tr>
<td wicket:id="filterTool"></td>
<td> <input wicket:id="search" type="submit" name="search" value="search"/> <input wicket:id="clear" type="submit" name="clear" value="clear"/></td>
</tr>
</tbody>
</table>
<table wicket:id="data">
<tbody >
<tr wicket:id="rows">
<td wicket:id="repeatingView"></td>
<td> <input type="submit" wicket:id="delete" class="submitLink"/></td>
</tr>
</tbody>
<tfoot>
<tr>
<td wicket:id="navigator"></td>
<td></td>
</tr>
</tfoot>
</table>
<input type="submit" wicket:id="Save" value="Save" align="left"/>
</form>
</wicket:panel>
FirstWicketHome.jave :
public class FirstWicketHome extends WebPage{
public FirstWicketHome()
{
List<ComponentEntity> emptyList = new ArrayList<ComponentEntity>();
//fill the list emptyList with datas
TestFormPanel testPanel=new TestFormPanel("sortingPanel", emptyList,new ComponentEntity());
add(testPanel);
}
}
FirstWicketHome.Html:
<html>
<body>
<div wicket:id="sortingPanel"/>
</body>
</html>
FirstWicketApplication.java
public class FirstWicketApplication extends WebApplication{
@Override
public Class<? extends Page> getHomePage() {
return FirstWicketHome.class;
}
}