Reputation: 314
I'm attempting to extend the Wicket Library Repeaters/Contacts Editor example so that I can save the row I'm editing, but it doesn't update after I've changed the values.
Debugging the code, it appears that
(User) ActionPanel.this.getDefaultModelObject()
does not get an updated Model Object, just the one that was originally used to populate the RefreshingView.
This is the code I have at the moment:
UserAdmin.java
package wicketsandbox.pages;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RefreshingView;
import org.apache.wicket.markup.repeater.util.ModelIteratorAdapter;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.protocol.http.WebApplication;
import wicketsandbox.AccessProtector;
import wicketsandbox.DetachableUserModel;
import wicketsandbox.User;
import wicketsandbox.WicketSandboxApplication;
import wicketsandbox.panels.SignOutPanel;
import wicketsandbox.services.UserService;
public class UserAdmin extends WebPage {
private static final long serialVersionUID = 1425344451953935626L;
private Form<User> form;
private final FeedbackPanel feedbackPanel;
private RefreshingView<User> contactsGrid;
private WebMarkupContainer updateableContactsForm;
public UserAdmin() {
new AccessProtector().userIsLoggedIn();
Map<UUID, User> users = getUserService().getUsers();
List<User> usersList = new ArrayList<User>();
usersList.addAll(users.values());
addContactsGridForm(usersList);
this.add(new SignOutPanel("signOutPanel"));
feedbackPanel = new FeedbackPanel("feedbackPanel");
feedbackPanel.setOutputMarkupId(true);
this.add(feedbackPanel);
}
private UserService getUserService() {
return ((WicketSandboxApplication) WebApplication.get()).getUserService();
}
private void addContactsGridForm(final List<User> users) {
updateableContactsForm = new WebMarkupContainer("updateableContactsForm");
form = new Form<User>("contactsForm");
contactsGrid = new RefreshingView<User>("contactsGrid") {
private static final long serialVersionUID = 6885639412244652087L;
@Override
protected Iterator<IModel<User>> getItemModels() {
return new ModelIteratorAdapter<User>(users) {
@Override
protected IModel<User> model(User user) {
System.out.println("L81" + user.toString());
return new CompoundPropertyModel<User>(new DetachableUserModel(user));
}
};
}
@Override
protected void populateItem(Item<User> item) {
IModel<User> user = item.getModel();
System.out.println("L90" + user.toString());
item.add(new Label("id"));
item.add(new TextField<String>("name", new PropertyModel<String>(user, "name")));
item.add(new TextField<String>("username", new PropertyModel<String>(user, "username")));
item.add(new TextField<String>("role", new PropertyModel<String>(user, "role")));
item.add(new CheckBox("deleted", new PropertyModel<Boolean>(user, "deleted")));
item.add(new ActionPanel("actions", user));
}
};
updateableContactsForm.setOutputMarkupId(true);
form.add(contactsGrid);
updateableContactsForm.add(form);
this.add(updateableContactsForm);
}
private class ActionPanel extends Panel {
private static final long serialVersionUID = -2270412980024700449L;
public ActionPanel(String id, final IModel<User> user) {
super(id, user);
System.out.println("L111" + user.toString());
add(new AjaxLink<String>("save") {
private static final long serialVersionUID = -1678664978510212524L;
@Override
public void onClick(AjaxRequestTarget target) {
getUserService().updateUser((User) ActionPanel.this.getDefaultModelObject());
System.out.println("L120" + user.toString());
info("User Saved: " + user.getObject().getName().toString());
target.add(feedbackPanel);
}
});
add(new AjaxLink<String>("select") {
private static final long serialVersionUID = 4555384514269762524L;
@Override
public void onClick(AjaxRequestTarget target) {
System.out.println("L132" + user.toString());
info("User Information: " + user.getObject().toString());
target.add(feedbackPanel);
}
});
AjaxSubmitLink removeLink = new AjaxSubmitLink("remove", form) {
private static final long serialVersionUID = 3030918214811303564L;
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
User user = (User) ActionPanel.this.getDefaultModelObject();
System.out.println("L145" + user.toString());
getUserService().removeUser(user);
info("Removed user " + user);
target.add(feedbackPanel);
target.add(updateableContactsForm);
}
};
removeLink.setDefaultFormProcessing(false);
add(removeLink);
}
}
}
DetachableUserModel.java
package wicketsandbox;
import java.util.Map;
import java.util.UUID;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.protocol.http.WebApplication;
public class DetachableUserModel extends LoadableDetachableModel<User> {
private static final long serialVersionUID = 2518759982972547608L;
private final UUID id;
protected Map<UUID, User> getContacts() {
return ((WicketSandboxApplication) WebApplication.get()).getUserService().getUsers();
}
public DetachableUserModel(User u) {
this(u.getId());
}
public DetachableUserModel(UUID id) {
if (id == null) {
throw new IllegalArgumentException();
}
this.id = id;
}
@Override
public int hashCode() {
return id.hashCode();
}
/**
* used for dataview with ReuseIfModelsEqualStrategy item reuse strategy
*
* @see org.apache.wicket.markup.repeater.ReuseIfModelsEqualStrategy
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
} else if (obj == null) {
return false;
} else if (obj instanceof DetachableUserModel) {
DetachableUserModel other = (DetachableUserModel) obj;
return other.id == id;
}
return false;
}
/**
* @see org.apache.wicket.model.LoadableDetachableModel#load()
*/
@Override
protected User load() {
return ((WicketSandboxApplication) WebApplication.get()).getUserService().getUser(id);
}
}
Upvotes: 0
Views: 1136
Reputation: 314
I've managed to solve this by using an AjaxFormComponentUpdatingBehavior for each field that was editable.
contactsGrid = new RefreshingView<User>("contactsGrid") {
private static final long serialVersionUID = 6885639412244652087L;
@Override
protected Iterator<IModel<User>> getItemModels() {
return new ModelIteratorAdapter<User>(getUserService().getUsers().values()) {
@Override
protected IModel<User> model(User user) {
return new CompoundPropertyModel<User>(new DetachableUserModel(user));
}
};
}
@Override
protected void populateItem(final Item<User> item) {
final IModel<User> user = item.getModel();
item.add(new Label("id"));
item.add(new TextField<String>("name").add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
item.setDefaultModelObject(user);
}
}));
item.add(new TextField<String>("username").add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
item.setDefaultModelObject(user);
}
}));
item.add(new TextField<String>("role").add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
item.setDefaultModelObject(user);
}
}));
item.add(new CheckBox("deleted").add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
item.setDefaultModelObject(user);
}
}));
item.add(new ActionPanel("actions", user));
}
};
Upvotes: 1
Reputation: 5681
Your page is loading the users from the service once only:
Map<UUID, User> users = getUserService().getUsers();
List<User> usersList = new ArrayList<User>();
usersList.addAll(users.values());
addContactsGridForm(usersList);
You should get an up-to-date list from your service for each call to #getItemModels().
Upvotes: 0