Peter Jaloveczki
Peter Jaloveczki

Reputation: 2089

Wicket ListView ajax removes always removes last element in list

I have a way to add panels in a listview. Each panel is associated with an Object of type Type. I have an 'add' and an some 'remove' AjaxSubmitLinks. Both have setDefaultFormProcessing(false) because I want non-submitted / validated values to remain when someone add or removes an element. setReuseItems(true) is set for the ListView. Please see the code snippet below.

         ListView itemContainer = new ListView<Type>("list", getList()) {
            @Override
            protected void populateItem(final ListItem<Type> listItem) {
                final Component element = createComponent(listItem.getModel());
                listItem.add(element);
                listItem.add(new AjaxSubmitLink("remove") {

                    @Override
                    protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        getList().remove(listItem.getIndex());
                        target.add(wrapper);
                    }
                }.setDefaultFormProcessing(false));
            }
        };
        itemContainer.setReuseItems(true);
        add(itemContainer);
        add(new AjaxSubmitLink("add") {
            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                Type object = addObject();
                getList().add(object);
                target.add(wrapper);
            }

            @Override
            public boolean isVisible() {
                return getList().size() < DSAddableField.this.max && isEditable();
            }
        }.setDefaultFormProcessing(false));

Where wrapper contains everything, so everything is reloaded with Ajax. All works well, expcet no matter which remove link I click the last element is being removed. equals() method is overriden on Type based on a UUID check. I did a debug and it would seem to me that the right element is removed from the ListModel, but wrong values are sent down by the ajax response.

How can I get this to work? I tried to remove setReuseItem(true), but than the non-saved values for list items were not reloaded. (Panels contain lot of input fields)

Any suggestions?

UPDATE:

I already tried to remove the object with getList().remove(listItem.getModelObject()), this was second solution but still failed.

Regardless if I use remove by index or by modelobject the right element is being removed from the list when using debugger.

UDAPTE 2:

If I remove "final int index = listItem.getIndex();" the right element is removed opposed to the last one but when I add a new one to the list non saved inputs are cleared which is the original problem I'm trying to solve. Please advise.

Upvotes: 1

Views: 629

Answers (3)

Peter
Peter

Reputation: 1894

This belongs to your 2nd Edit:
If you use target.add(wrapper); you read the whole component and thus rerender it. If you put your populateItem in a WebMarkupContainer you can rerender only this item.

protected void populateItem(final ListItem<Type> listItem) {
    WebMarkupContainer cont = new WebMarkupContainer("cont");
    cont.setOutputMarkupId(true);
    cont.setOutputMarkupPlaceholderTag(true);
    final Component element = createComponent(listItem.getModel());
    cont.add(element);
    cont.add(new AjaxSubmitLink("remove") {
        @Override
        protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
           getList().remove(listItem.getIndex());
           target.add(cont);
        }
    }.setDefaultFormProcessing(false));    
    listItem.add(cont); 
}

Upvotes: 2

papkass
papkass

Reputation: 1289

I think the problem is listItem.getIndex();

When you call that method to get the index, listItem will be the last element in the list.

Try:

@Override
protected void populateItem(final ListItem<Type> listItem) {
    final Component element = createComponent(listItem.getModel());
    listItem.add(element);
    final int index = listItem.getIndex();
    listItem.add(new AjaxSubmitLink("remove") {
    @Override
    protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
        getList().remove(index);
        target.add(wrapper);
    }
    }.setDefaultFormProcessing(false));

Upvotes: 0

Peter
Peter

Reputation: 1894

I checked the solution I provided before in a comment myself, this should do it:

getList().remove(listItem.getModelObject());

Although I'm not sure if this would not just give a new List. I would do something like this:

List<Type> myList = getList();
ListView itemContainer = new ListView<Type>("list", myList) {
    myList.remove(listItem.getModelObject());
}

Upvotes: 0

Related Questions