thatidiotguy
thatidiotguy

Reputation: 9011

Using Wicket Repeater with backing Map

So essentially I want to use Wicket 1.5 to display an item and its associated quantity. The data structure I am using to back this is a Map (new HashMap()) where Item is a POJ whose details are of no consequence. Essentially I would like to use one of wicket's repeaters, but I only have experience using ListView. Is there a repeater that would work well with a Map, or am I going to need to code my own? If I need to code my own, what is the best class to override?

I would the output of the repeater to essentially be something like:

QuantityX : ItemName (ItemNum)

so for example:

2x : someItem (255609)

The map can change through user input, but I am familiar with refreshing component's markup with AJAX via Wicket. Your help is much appreciated.

Upvotes: 3

Views: 2054

Answers (3)

Ondra Žižka
Ondra Žižka

Reputation: 46876

See this article: Wicket Model magic: Map-backed ListView

public CustomFieldsPanel( String id, final IModel<Map<String,ProductCustomField>> fieldMapModel, final FeedbackPanel feedbackPanel ) {

    super( id, fieldMapModel );
    this.feedbackPanel = feedbackPanel;

    this.setOutputMarkupId( true ); // AJAX JavaScript code needs to have some id="...".

    IModel<List<ProductCustomField>> listModel = new LoadableDetachableModel() {
        @Override protected List<ProductCustomField> load() {
            Map<String,ProductCustomField> map = (Map) CustomFieldsPanel.this.getDefaultModelObject();
            return new ArrayList(map.values());
        }
    };

    ListView<ProductCustomField> listView;
    add( listView = new ListView<ProductCustomField>("fieldsRows", listModel){
        @Override
        protected void populateItem( final ListItem<ProductCustomField> item ) {
            item.add( new CustomFieldRowPanel("fieldRow", item.getModel()){
                // Delete icon was clicked.
                @Override
                protected void onDelete( AjaxRequestTarget target ) {
                    Map<String,ProductCustomField> fieldsMap = (Map) CustomFieldsPanel.this.getDefaultModelObject();
                    fieldsMap.remove( item.getModelObject().getName() );
                    target.add( CustomFieldsPanel.this ); // Update UI.
                    try {
                        CustomFieldsPanel.this.onChange( target ); // Persists.
                    } catch (Exception ex){
                        feedbackPanel.error( ex.toString() );
                    }
                }
            });
        }
    });
    ...
}

Upvotes: 0

thatidiotguy
thatidiotguy

Reputation: 9011

I ended up using ListView where the ListView Model held Map.Entry as suggested by Thorsten above. It works as intended, and thank you Thorsten.

Upvotes: 1

Mar Cel
Mar Cel

Reputation: 420

One option would be to use your Listview and feeding it with a list you can retrive from the map like Arrays.asList(HashMap#values#toArray) Generally I prefer the Loop to Reapeat stuff, because you just provide an Integer Model like AbstractReadOnlyModel to define the number of iterations. In this case you can easyly build your own models an helper methods to get the data from anywhere. I you really want to build your own repeater you should extend AbstractRepeater but you should rather build around Loop.

Upvotes: 0

Related Questions