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

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.

Related

Onsubmit of form, page get refreshed and PageParameters gets empty in wicket

In LoginPage.java, I have added some PageParameters and redirect the user to another page.
PageParameters parameters = new PageParameters();
parameters.add("firstName", firstNameValue);
parameters.add("lastName", lastNameValue);
parameters.add("emailAddress", emailAddressValue);
throw new RedirectToPageException(UserInformationPage.class, parameters);
In AdditionalInformationPage.java
public class UserInformationPage extends BaseWebPage {
private static final long serialVersionUID = 3614392599102678526L;
public UserInformationPage(final PageParameters parameters) {
super(parameters);
setOutputMarkupId(true);
String firstName, lastName, emailAddress;
firstName = parameters.get("firstName").toOptionalString();
lastName = parameters.get("lastName").toOptionalString();
emailAddress = parameters.get("emailAddress").toOptionalString();
WebMarkupContainer userInformationPageWrapper = new WebMarkupContainer("userInformationPageWrapper");
userInformationPageWrapper.add(new UserInformationPanel("userInformationPageContent", firstName, lastName, emailAddress));
add(userInformationPageWrapper.setMarkupId("userInformationPageWrapper"));
}
}
UserInformationPanel.java
public class UserInformationPanel extends Panel {
private static final long serialVersionUID = -1016518626600751985L;
public UserInformationPanel(String id, String idpUuid, firstName, lastName, emailAddress) {
super(id);
setOutputMarkupId(true);
Form<Void> userInformationForm = new CSRFSafeForm<Void>("userInformationForm") {
private static final long serialVersionUID = 2633350725131958527L;
#Override
protected void onConfigure() {
super.onConfigure();
setVisible(true);
}
};
FeedbackPanel errorFeedbackPanel = new TrackedFeedbackPanel("errorFeedback", new ErrorLevelFeedbackMessageFilter(FeedbackMessage.ERROR));
errorFeedbackPanel.setMaxMessages(MAX_ERROR_MESSAGES);
userInformationForm.add(errorFeedbackPanel.setOutputMarkupId(true));
TextField<String> firstName = new TextField<>("firstName", firstName);
firstName.add(StringValidator.maximumLength(DatabaseConstants.User.FIRST_NAME_MAX_LENGTH));
userInformationForm.add(firstName.setRequired(true).setEnabled(true));
TextField<String> lastName = new TextField<>("lastName", lastName));
lastName.add(StringValidator.maximumLength(DatabaseConstants.User.LAST_NAME_MAX_LENGTH));
userInformationForm.add(lastName.setRequired(true).setEnabled(true));
EmailAddressValidator emailAddressValidator = EmailAddressValidator.getInstance();
TextField<String> emailAddress = new EmailTextField("emailAddress", emailAddress), emailAddressValidator);
emailAddress.setRequired(false)
.add(UniqueEmailValidator.getInstance(UniqueEmailValidator.ErrorMsgType.REGISTER))
.add(StringValidator.maximumLength(DatabaseConstants.EMAIL_ADDRESS_MAX_LENGTH));
emailAddress.setEnabled(false);
userInformationForm.add(emailAddress);
userInformationForm.add(new AjaxButton("submitButton") {
private static final long serialVersionUID = -1723378347103997463L;
#Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
super.onSubmit(target, form);
Map<String, Object> userAttributes = new LinkedHashMap<>();
userAttributes.put("email_Address", emailAddress);
userAttributes.put("first_Name", firstName);
userAttributes.put("last_Name", lastName);
// logic to save userAttributes in DB.
throw new RedirectToUrlException("/home");
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
super.onError(target, form);
target.add(errorFeedbackPanel);
}
});
userInformationForm.setOutputMarkupId(true);
add(userInformationForm);
}
}
Button in html file like this:
<button wicket:id="submitButton" type="submit" class="adb-button__primary nextStep">
<span><wicket:message key="Submit"/></span>
</button>
First time page gets rendered successfully. Fields get pre-populated. When I click on submit buttton first time, the page gets refreshed and page parameters gets empty. Form is rendered again but with empty values. On second click it works properly.
So, How can I stop page refresh so that pageParams does not gets empty and on click of submit button in first time, it validates the form and show error if any on page?
I couldn't add a comment so I am suggesting this answer.
Please check this line : throw new RedirectToUrlException("/home"); inside the onSubmit() method. Why are you using it? This means that you are redirecting to /home whenever the user submits the form, and probably at home your are redirecting back to the LoginPage. Please check what is happening at the /home route, or post more information so I can help you better.

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.

Attempt to set model object on null model of component: form:checkgroup

I'm trying to create a list of HITs (objects), where each has a checkbox next to it, so that I can select them and delete them all at once. I've made a form with a checkbox for each row in the table:
final HashSet<HIT> selectedValues = new HashSet<HIT>();
final CheckGroup checkgroup = new CheckGroup("checkgroup");
final Form form = new Form("form"){
#Override
public void onSubmit() {
super.onSubmit();
}
};
checkgroup.add(new CheckGroupSelector("checkboxSelectAll"));
UserHitDataProvider userHitDataProvider = new UserHitDataProvider(selectedIsReal, keyId, secretId);
final DataView<HIT> dataView = new DataView<HIT>("pageable", userHitDataProvider) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem(final Item<HIT> item) {
HIT hit = item.getModelObject();
item.add(new CheckBox("checkbox", new SelectItemUsingCheckboxModel(hit,selectedValues)));
item.add(new Label("hitName", String.valueOf(hit.getTitle())));
item.add(new Label("hitId", String.valueOf(hit.getHITId())));
}
};
//add checkgroup to form, form to page, etc.
I've also added a new class to take care of the selection/deletion:
public class SelectItemUsingCheckboxModel extends AbstractCheckBoxModel {
private HIT hit;
private Set selection;
public SelectItemUsingCheckboxModel(HIT h, Set selection) {
this.hit = h;
this.selection = selection;
}
#Override
public boolean isSelected() {
return selection.contains(hit);
}
#Override
public void select() {
selection.add(hit);
}
#Override
public void unselect() {
selection.remove(hit);
}
}
Everything renders fine, but I get an error when trying to submit:
Caused by: java.lang.IllegalStateException: Attempt to set model object on null model of component: form:checkgroup
at org.apache.wicket.Component.setDefaultModelObject(Component.java:3042)
at org.apache.wicket.markup.html.form.FormComponent.updateCollectionModel(FormComponent.java:1572)
at org.apache.wicket.markup.html.form.CheckGroup.updateModel(CheckGroup.java:160)
at org.apache.wicket.markup.html.form.Form$FormModelUpdateVisitor.component(Form.java:228)
at org.apache.wicket.markup.html.form.Form$FormModelUpdateVisitor.component(Form.java:198)
at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:274)
at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:262)
at org.apache.wicket.util.visit.Visits.visitPostOrder(Visits.java:245)
at org.apache.wicket.markup.html.form.FormComponent.visitComponentsPostOrder(FormComponent.java:422)
at org.apache.wicket.markup.html.form.Form.internalUpdateFormComponentModels(Form.java:1793)
at org.apache.wicket.markup.html.form.Form.updateFormComponentModels(Form.java:1757)
at org.apache.wicket.markup.html.form.Form.process(Form.java:913)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:770)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:703)
... 27 more
I think its some of the Ajax code breaking, since my SelectAllCheckBox button is also failing. Any ideas why? Is this even the best way to handle such a use case?
Your Checkgroup does not have a Model, thus Wicket can't copy the current state of the Model into a null object. You should use the constructor with an additional parameter representing the Model you want to store the value in.

How to concatenate 2 textboxes in wicket?

So i got these 2 text boxes and I'm trying to concatenate them together and show the result in label. I found an example and did it like in the example but something is wrong. So maybe some one can see what I am doing wrong, because i have just started and don't understand how to do it properly.
public class HomePage extends WebPage {
private String fNumber="Big";
private String sNumber=" text!";
private String sResult=fNumber+sNumber;
public HomePage() {
PropertyModel<String> firstNumber = new PropertyModel<String>(this, "fNumber");
PropertyModel<String> secondNumber = new PropertyModel<String>(this, "sNumber");
add(new Label("message", "HelloWorld!"));
add(new Label("result", sResult));
Form<?> form = new Form("form");
form.add(new TextField<String>("firstNumber", firstNumber));
form.add(new TextField<String>("secondNumber", secondNumber));
add(form);
}
}
soo i have made this
` add(new Label("message", "HelloWorld!"));
add(new Label("result", new Model(numb.getsResult())));
Form<?> form = new Form("form") ;
form.add(new TextField<String>("firstNumber", new Model(numb.setfNumber())));
form.add(new TextField<String>("secondNumber",new Model(numb.setsNumber())));
add(form);`
and i have a class that has 3 string fields and getters and setters and sii that much i have understood last comment explained some things maybe some one know how to fix this.
You need to "recalculate" your result. The Wicket way would be to define a Model for your Label that does the concatenation.
add(new Label("result", new IModel<String>(){
#Override
public void detach() {
// do nothing
}
#Override
public String getObject() {
return fNumber + sNumber;
}
#Override
public void setObject(String object) {
// do nothing
}
}));
Additionally you must use the PropertyModels from the example.
To concatenate two strings I usually use StringBuilder:
PropertyModel firstNumber = new PropertyModel(this,"fNumber");
PropertyModel secondNumber = new PropertyModel(this,"sNumber");
PropertyModel resultNumber = new PropertyModel(this,"sResult");
StringBuilder sResult = new StringBuilder((String) firstNumber.getObject());
sResult.append((String) secondNumber.getObject());
resultNumber.setObject(sResult.toString());
Also, please read the link from biziclop as it should help you significantly.