Onsubmit of form, page get refreshed and PageParameters gets empty in wicket - 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.

Related

Apache Wicket TextField

Good day!
I create some Table:
List<IColumn<User, String>> columns = new ArrayList<>();
columns.add(new AbstractColumn<User, String>(new Model<String>("")) {
#Override
public void populateItem(Item<ICellPopulator<User>> cellItem, String componentId, IModel<User> rowModel) {
cellItem.add(new Link<String>(componentId) {
#Override
public void onClick() {
System.out.println("editors" + rowModel.getObject().getName());
PageParameters parameters = new PageParameters();
parameters.add("id", rowModel.getObject().getId());
add(new EditPanel("panel", rowModel));
}
#Override
public IMarkupFragment getMarkup() {
return Markup.of("<div wicket:id='cell'> edit </div>");
}
});
}
When I click on cell into Table, cell markup "Edit", I create some Panel:
public class EditPanel extends Panel {
public EditPanel(String id, IModel<User> model) {
super(id, model);
User user = model.getObject();
if (user == null) {
user = new User();
}
List<UserRole> list = Arrays.asList(UserRole.values());
Form<?> form = new Form("form", new CompoundPropertyModel(user));
TextField<String> userName = new TextField<String>("name");
};
add(new FeedbackPanel("feedback"));
add(form);
form.add(userName);
}
}
How can I set value to
TextField userName = new TextField("name");
from my model, or if model == null, set any text what I need?
Thanks!
If you use Wicket 7 or older then you may use :
TextField<String> userName = new TextField<String>("name", new PropertyModel(model, "username"));
assuming that username is a property of User.
With Wicket 8.x you can use LambdaModel instead.
Heyy,
I think the problem is because you are passing the object and not the model.
The right way is passing with CompoundPropertyModel, like you do. It`s better then PropertyModel in this case.
Try doing this:
...
if (model.getObject() == null) {
model.setObject(new User());
}
Form<?> form = new Form("form", new CompoundPropertyModel(model));
...
Hope help you.

passing parameters to wicket panel

firstly wish you all a very happy new year.
i am moving my data tables in to a panel from webpage. i was using pageparameters to pass required parameters on clicking the link for retrieving data and displaying it in the next page. now that i have moved those tables in to a panel i am not sure how to forward those parameters in panels.
My calling Method:
final TextField<String> jobnumber = new TextField<String>("jobnumber ", Model.of(""));
jobnumber .setRequired(true);
final TextField<String> jobtype= new TextField<String>("jobtype", Model.of(""));
jobtype.setRequired(true);
Form form = new Form("form") {
#Override
public void onSubmit() {
final String jobnumber = jobnumber .getModelObject();
final String jobtype= jobtype.getModelObject();
PageParameters params= new PageParameters();
params.add("jobnumber ", jobnumber );
params.add("jobtype", jobtype);
new Job("jobs", params);
}
};
Button button = new Button("button");
form.add(button);
form.add(jobnumber);
form.add(jobtype);
add(form);
My Panel Constructor:
public class Job extends Panel {
public Job(String id, **PageParameters params**) {
super(id);
String jobnumber = params.get("jobNumber").toString();
String jobtype= params.get("jobtype").toString();
add(new Label("jobNumberLabel", jobnumber));
add(new Label("jobtypeLabel", jobtype));
list = retrieveJob(jobnumber, jobtype);
add(new ListView("agilejobs1", list) {
#Override
protected void populateItem(ListItem item) {
final Job job = (Job) item.getModelObject();
item.add(new Label("jobNumber", job.getJobNumber()));
item.add(new Label("jobdesc", job.getJobdesc()));
item.add(new Label("jobcount", job.getJobCount()));
}
});
}
}
i have tried to replace PageParameters with IModel but it did not work.
Please suggest.
Thanks
I would use a IModel<List<Job>>. You can create one in your panel like this:
public class JobPanel extends Panel {
public JobPanel(String id, String jobnumber, String jobtype) {
super(id);
IModel<List<Job>> jobListModel = new ListModel<Job>(retrieveJob(jobnumber,jobtype));
add(new ListView("agilejobs1", jobList) {
#Override
protected void populateItem(ListItem item) {
final Job job = (Job) item.getModelObject();
item.add(new Label("jobNumber", job.getJobNumber()));
item.add(new Label("jobdesc", job.getJobdesc()));
item.add(new Label("jobcount", job.getJobCount()));
}
});
}}
However, it would be better to construct the IModel<List<Jobs>> outside of the Panel and just pass it as an argument. The creation/setting of the model can be done in an Page, an onSubmit() in a Form or whatever method you like. Then the code becomes much cleaner, as the JobPanel will only be responsible for showing the data.

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.

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.