gwtuibindergwt-tablayoutpanel

TabLayoutPanel selection handler triggers multiple times


Currently I'm working with GWT TabLayoutPanel and got some problems. My application uses Activities and Places to manage browser history. With TabLayoutPanel I'm trying to store tabs in history by doing placeController.goTo() in onSelectionHandler() event (so that I can move back on browser). I'm refreshing Tabs list doing tabLayoutPanel.clear(). The problem is that tabPanel.clear() triggers selectionHandler multiple times and thus my Places triggers many times. To fix that behavior I had to add local enabling and disabling of SelectionHandler, but that doesn't looks proper for me.

Below is code examples. I'm using addEvents method to refresh list of tabs on some events.

@UiField
TabLayoutPanel tabPanel;
private Boolean enabledSelectionHandler = true;
...
    public EventsPageImpl(EventBus bus, final PlaceController placeController) {
        initWidget(uiBinder.createAndBindUi(this));
        tabPanel.addSelectionHandler(new SelectionHandler<Integer>() {
            @Override
            public void onSelection(SelectionEvent<Integer> event) {
                if (enabledSelectionHandler) {
                    if (eventsList.size() > 0 && event.getSelectedItem() != 0) {
                        placeController.goTo(new EventsPlace(eventsList.get(event.getSelectedItem() - 1).getId().toString()));
                    } else {
                        placeController.goTo(new EventsPlace(null));
                    }
                }


}
    });
...
}

@Override
public void addEvents(List<ClientEvent> events) {
    enabledSelectionHandler = false;
    tabPanel.clear();
    tabPanel.add(new EventsTab(presenter), CommonMessages.INSTANCE.createNewEvent());
    if (eventsList.size() == 0 && events.size() > 0) {
        for (ClientEvent event : events) {
            eventsList.add(event);
        }
    }
    for (ClientEvent event : eventsList) {
        tabPanel.add(new EventsTab(event, presenter), event.getTitle());
    }
    enabledSelectionHandler = true;
}

Is there any other proper way without local enabledSelectionHandler usage to prevent SelectionHandler being triggered multiple times?


Solution

  • The behavior of the TabLayoutPanel panel is correct. When you call clear the TabLayoutPanel remove each tab one by one. When you remove a tab, the last tab is selected -> sending the selection event. So when you clear a TabLayoutPanel with n elements you should have n-1 selection event raised.

    I think your solution is good but maybe you could use the handler registration to enable/disable listening to the event

    final HandlerRegistration registration = tabPanel.addSelectionHandler(this);
    registration.removeHandler();
    

    Alse consider using the BeforeSelectionEvent to enable/disable the event