# ListmodelList shared on multiple components

MaurizioB
1 1

I've noticed a problem by using the same ListModelList as the model of multiple components (combobox/chosenbox) with different selectedItems binding.

Basically changing the selection in one of the component changes the shown selection in every other component sharing the ListModelList as model.

I found a fiddle search for "zkfiddle.org/sample/2tl5ndm/7-ListModelList-used-in-multiple-components#source-1" that reproduce the issue using comboboxes.

Is this a known bug? How do you fix it?

delete retag edit

Sort by » oldest newest most voted

cor3000
4332 1 7

Hi Maurizio,

this is exactly the expected behavior when sharing the same ListModel implementation between multiple components.

The ListModelList implements the Selectable interface, that's why it keeps track of the current selection and propagates that among all attached components.

If you just want to share the same item list and without sharing the selection, simply use an ArrayList<integer> or Integer[] to share the same items, but have a separate selection state in each combobox.

see -> updated zkfiddle

This conversion from List/Array into a ListModel will automatically happen by the default converter ComboboxModelConverter

If you want to preserve the memory and avoid copying the items into each ListModel you can create a live-ListModel for each combobox referencing the same collection:

modelForComboA = new ListModelList(items, true /*live*/);
modelForComboB = new ListModelList(items, true /*live*/);


Robert

MaurizioB
1 1

Hi Robert, thank you for the answer, while it is the expected behaviour, the selection doesn't match what is stored in the "selectedItem" variables thus creating a mismatch between the visuals and the Java part.

Because of this mismatch I do not see a use case where it would be beneficial to have the same ListModel shared, but if it is a technical limit of the Selectable, it would be nice to have this mentioned in the documentation.

That said I still need to use the ListModelList for scrolling purposes (I am using listboxes,not comboboxes), so will opt for the different ListModels (maybe live). With this approach adding an element to one of them will not update the others or will they update correctly without losing the scroll?

cor3000
4332 1 7

Hi Maurizio,

I am sorry if this sounds like I am arguing with you (this is not my intention) ... I am just trying to explain what is happening and that your current usage won't bring your desired results.

Besides I can imagine scenarios where shared selection state is useful e.g 2 separate navigation controls (a combobox and a tabbox driven by the same model. Providing 2 redundant controls to choose the current tab in a tabbox) - anyway that's a matter of personal preference whether that's useful or not.

Given that: using a ListModel that implements Selectable only keeps track of a single set of selected items. Shared among both models. That's not a limitation, that's a feature intended to keep a model driven UI in synch.

If you combine the approaches selectedItem + sharing a model you simply implemented redundant state that can get out-of-synch or replicate in a unwanted way.

I am not completely clear how that relates to scrolling... maybe you can provide an example showing where a ListModel is needed for scrolling. A listbox is scrollable when the number of items exceeds the visible listbox body (if limited in size).

If you are referring to a "Load on demand" ListModel then sharing the same ListModel for 2 listboxes may also give unexpected results. If both have different scroll positions, then the same model suddenly has to load elements for visible different ranges. Also there separating the models is preferable in my opinion.

I agree that the approach of using a live list model will serve your purpose best - given the details you shared so far.

Robert

cor3000
4332 1 7

With this approach adding an element to one of them will not update the others or will they update correctly without losing the scroll?

again I don't see the relation to scrolling.

About adding elements: I can only refer to the related documentation -> adding an element to the Model will affect the inner collection and not vise versa. So if 2 models share the same inner collection this will lead to inconsistencies as well. When adding an element to one model will not notitify the other model that something was added. And if you add/remove then from the other model you are likely to get IndexOutOfBounds exceptions. If you are just referring to adding removing elements from selection then there's no conflict.

If you need separate items, simply use separate ListModelLists each with a copy of the elements.

MaurizioB
1 1

Relation to scrolling: By using a simple ArrayList if you add/remove an element of the list the listbox re-renders the elements sending you to the top of the list (losing the scroll) instead of leaving you where you've added/removed the element.

By reading the documentation this problem is solved by using the ListModel, but unfortunately the sync problem appeared.

I basically need 2+ long lists that retain the screen position when elements are added/removed but do not share the same selection of elements (and save the selected items to 2 different lists). Based on the answers seems that 2+ separated,not live ListModels where I add/remove from each one (and the underlaying list) to mantain them aligned is the solution.

now I understand... scrolling itself is not broken (since a scrollbar will always remain) but you wanted to preserve the scroll position when updating the model... for this you definitely have to add single items either through listmodel MVVM or MVC direct component access

( 2017-10-30 14:58:56 +0800 )edit

cor3000
4332 1 7

Thanks for the clarification.

If memory is a concern you can implement your own ListModel without Selectable:

And take what you need from: https://github.com/zkoss/zk/blob/master/zul/src/org/zkoss/zul/AbstractListModel.java

[hide preview]