How to repeat downloadLink inside repeatingView Wicket? - wicket

I'm working on wicketpage where I want to display a dynamic table contains two columns.
The first column should have a DownloadLink. The second column holds a simple label.
The problem is wicket displaying an empty first column so I can't see the downloadlink.
How can I add a label to the downloadLink in this case ?
ListDataProvider<String> listDataProvider = new ListDataProvider<String>(filesPaths);
DataView<String> dataView = new DataView<String>("rows", listDataProvider) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem(Item<String> item) {
String filePath = item.getModelObject();
RepeatingView repeatingView = new RepeatingView("dataRow");
String idLink = repeatingView.newChildId();
DownloadLink link = new DownloadLink(idLink, new File(filePath));
link.add(new Label(idLink + "label", filePath));
repeatingView.add(link);
Label label = new Label(repeatingView.newChildId(), "(TEST)");
label.add(new AttributeModifier("style", "color: blue;"));
repeatingView.add(label);
item.add(repeatingView);
}
};
add(dataView);
This is a section of the html page.
<table>
<tr wicket:id="rows">
<td wicket:id="dataRow"></td>
</tr>
</table>

You can set the Links name like the following:
downloadLink.setBody(Model.of("Download"));
This will set the link to Download

Related

Wicket get button component text

I would like to get the text of a button submitProceed and will use it in my code/logic.
HTML
<button wicket:id="submitProceed" type="button" class="btn btn-sm btn-primary btn-save" disabled="disabled">Submit</button>
Is it possible to get the button text Submit? Also, how to I change this to Proceed?
This is how I initialize my button component:
private Component m_btnSubmit;
...
private Component createForm() {
Form<Void> result = new Form<>("form");
...
result.add(m_btnSubmit = createSubmit("submit"));
...
return result;
}
private Component createSubmit(String wicketId) {
AjaxButton result = new AjaxButton(wicketId) {
private static final long serialVersionUID = 1L;
#Override
protected void onConfigure() {
super.onConfigure();
...
setOutputMarkupId(true);
}
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
...
}
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
super.onSubmit(target, form);
// TODO: Get button text here
// Check button text if either `Submit` or `Proceed`
// Action depending on button text (Also change button text)
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
super.onError(target, form);
...
}
};
...
return result;
}
Solution:
First of All, I would like to thank #Andrea and #martin for their solution, I just tweak it a bit for fit my existing code.
Since I need a span containing the text Submit and later be changed to Proceed... I need to add a span inside button tag like this:
<button wicket:id="submit" type="button"><span wicket:id="labelSubmit">Submit</span&lg;</button>
the problem with this, I am getting an error that seems it would not allow button to have a nested component.
Error is something like this:
org.apache.wicket.markup.MarkupException: Expected close tag for '<button wicket:id="submit" type="button">' Possible attempt to embed component(s) '<span wicket:id="labelSubmit">' in the body of this component which discards its body.
To fix this, I need to change from button to a so it would look like this:
<a wicket:id="submit" type="submit"><span wicket:id="labelSubmit">Submit</span&lg;</a>
...
IModel m_labelModel = Model.of("Submit");
Label m_labelSubmit = new Label("labelSubmit", m_labelModel);
m_labelSubmit.setOutputMarkupId(true);
...
In my button's onSubmit:
m_labelModel.setObject("Proceed");
target.add(this);
Note that I only did change m_labelModel, but I need to add the current button (this) so that the change will reflect in the UI.
For those, having the same issue or setup... hope this helps :)
If you use new AjaxButton(String, IModel) constructor, as Andrea Del Bene suggested, then the model will be used to set the value attribute of the button:
<button value="Submit"></button>
If you need to manipulate the textContent of the <button>, i.e. <button>!!!THIS!!!</button> then you can add a Label component as a child:
IModel<String> labelModel = Model.of("Submit");
Label label = new Label("labelId", labelModel);
label.setOutputMarkupId(true);
button.add(label);
...
In AjaxButton#onSubmit(AjaxRequestTarget target) you can update it:
labelModel.setObject("New value");
target.add(label);
you should use button's constructor that takes also a model as button's label:
IModel labelModel = Model.of("Submit");
new Button<>("submit", labelModel);
Than you can use the model to get/set this value

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.

Google Web Toolkit - How to prevent duplication of the records?

I am new in GWT. I am trying to use the cell table to do this. Here is my questions:
Name Gender
Ali M
Abu M
Siti F
page 1
Name Gender
Siti F
Noor F
Ahmad F
page 2
I use simple pager to do the paging function. Everything is ok except next page.
When i click next page, siti record appear 2 times.
How to prevent the name Siti not appear in page 2? Below are my code:
private static class Contact{
private final String name;
private final String gender;
public Contact(String name, String gender){
this.name = name;
this.gender = gender;
}
}
private static final List<Contact> CONTACTS = Arrays.asList(
new Contact("Ali","M"),
new Contact("Abu","M"),
new Contact("Siti","F"),
new Contact("Noor","F"),
new Contact("Ahmad","M")
);
public void onModuleLoad(){
final CellTable<Contact> table = new CellTable<Contact>();
table.setPageSize(3);
TextColumn<Contact> nameColumn = new TextColumn<Contact>(){
#Override
public String getValue(Contact object) {
return object.name;
}
};
TextColumn<Contact> genderColumn = new TextColumn<Contact>(){
#Override
public String getValue(Contact object) {
return object.gender;
}
};
table.addColumn(nameColumn, "Name");
table.addColumn(genderColumn, "Gender");
AsyncDataProvider<Contact> provider = new AsyncDataProvider<Contact>(){
#Override
protected void onRangeChanged(HasData<Contact> display) {
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
end = end >= CONTACTS.size() ? CONTACTS.size() : end;
List<Contact> sub = CONTACTS.subList(start,end);
updateRowData(start,sub);
}
};
provider.addDataDisplay(table);
provider.updateRowCount(CONTACTS.size(), true);
SimplePager.Resources pagerResources = GWT.create(SimplePager.Resources.class);
SimplePager pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0, true);
pager.setDisplay(table);
Please help me to solve this problem. Thanks.
You have faced most probably the gwt last page problem, described in the linked questions:
GWT - celltable with simple pager issue
SimplePager row count is working incorrectly
The solution here is to set:
setRangeLimited(false)
and the last page is paged correctly, ie. it contains only Noor and Ahmad.
So in conclusion: actually no duplication is present here, but a bug on pagination in case of the last page. You will observe the same behavior with also other amounts of data, but on my view point it would be always a last page issue only.

Add filters to LiveGrid?

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.

Display Field for select item in the list grid

Hello all
I am using smart gwt 2.2 on windows with mozilla browser.
I am using a list grid with two fields.
I set the editor type of second field to SelectItem.
In that select item I am rendering a grid.
For select item I set the value field and the display field.
But after the select any item from select item it is display value field.
I am also attaching the code for it.
code for grid
public void initializeGrid() {
ListGrid grid = new ListGrid();
setGridProperty(grid);
grid.setFields(getGridFields());
grid.setData(getGridData());
getSmartContainer().addChild(grid);
}
private static ListGridRecord[] getGridData() {
ListGridRecord record = new ListGridRecord();
record.setAttribute("id", "");
record.setAttribute("name", "");
ListGridRecord record1 = new ListGridRecord();
record1.setAttribute("id", "");
record1.setAttribute("name", "");
return new ListGridRecord[] { record, record1 };
}
private static void setGridProperty(ListGrid grid) {
grid.setWidth("90%");
grid.setHeight(125);
grid.setCanEdit(true);
grid.setEditEvent(ListGridEditEvent.CLICK);
grid.setEditByCell(true);
grid.setAlternateRecordStyles(true);
grid.setShowAllRecords(true);
}
private static ListGridField[] getGridFields() {
ListGridField field = new ListGridField("id");
FormItem item = new TextItem();
field.setEditorType(item);
ListGridField field1 = new ListGridField("name");
SelectItem item1 = new SelectItem("name");
setPropertyForSelectitem(item1);
DataSource dataSource = new DataSource();
dataSource.setClientOnly(true);
item1.setOptionDataSource(dataSource);
setDataForSelectItem(dataSource);
field1.setEditorType(item1);
return new ListGridField[] { field, field1 };
}
Code for select item
public static void setDataForSelectItem(DataSource dataSource) {
for (int i = 0; i < 2; i++) {
ListGridRecord record = new ListGridRecord();
record.setAttribute("id", "1");
record.setAttribute("name", "name" + i);
record.setAttribute("address", "address" + i);
dataSource.addData(record);
}
}
private static void setPropertyForSelectitem(SelectItem item) {
item.setPickListFields(getFieldsForSelectItem());
item.setWidth(150);
item.setValueField("id");
item.setDisplayField("name");
item.setPickListWidth(250);
}
private static ListGridField[] getFieldsForSelectItem() {
ListGridField idField = new ListGridField("id");
ListGridField nameField = new ListGridField("name");
ListGridField addField = new ListGridField("address");
return new ListGridField[] {idField,nameField,addField };
}
[/CODE]
After drawing this grid it is rendering value field for the select item, but i want to render the name (as it is the display field for the select item).
Same select item I used in the dynamic form but it is working well at that place, but for the grid it is not working well.
Please Help.
Thanks