matthewh86
matthewh86

Reputation: 314

Trouble updating row in Wicket 6.0 RefreshingView example

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.

http://www.wicket-library.com/wicket-examples-6.0.x/repeater/wicket/bookmarkable/org.apache.wicket.examples.source.SourcesPage?SourcesPage_class=org.apache.wicket.examples.repeater.FormPage&source=FormPage.java

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

Answers (2)

matthewh86
matthewh86

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

svenmeier
svenmeier

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

Related Questions