tobiasdiez / EasyBind

Custom JavaFX bindings made easy with lambdas.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is there support for listening to changes in observables of the ObservableList items?

Adito5393 opened this issue · comments

commented

Great work on keeping the library alive and providing the JMPS support! đź‘Ť

The javafx offers the following implementation that does exacly this:
public static <E> ObservableList<E> observableArrayList​(Callback<E,​Observable[]> extractor) (see the javadocs)

The problem I have is that I have an ObservableList of TreeItems of my customClass that I would love to convert to an ObservableList.
I tried using EasyBind.map, however now the changes to the underlying data are not triggering the events changes (only the properies changes).
The good part is that when I add or remove items, the lists are in sync,

Using the extractor callback that looks something like this:

ObservableList<customClass> tasksList = FXCollections.observableArrayList(param -> new Observable[] {param.nameProperty()});

The UI gets the changes updates, minus the addition or subtraction of the items to the underlying list.

Can I use somehow EasyBind and pass a Callback<E,​Observable[]> extractor?

So what you want is that if a change to one of the items in the original list triggers an update of the mapped list as well?
This should be possible by providing the extractor on the original list as in the following code snippet

var list = FXCollections.observableArrayList(param -> extractor logic here);
// Fill list etc
var mapped = EasyBind.map(list);

Now mapped should be updated if items in list are changed.

If that doesn't work, could you please provide a simple code example - in the best case as a failing unit test.

commented

Correct!

Unfortunately, I can not modify the way the observableArrayList is created (can't attach the extractor logic at initialization time) because I obtain it from the TreeItem method getChildren().

I tried using 2 methods from EasyBind: EasyBind.map and EasyBind.flatten:

Here is the code I used that does not trigger changes to the underlying properties changes:

// finalTasksList is needed to combine all lists available under Root TreeItem: esmCore
ObservableList<ObservableList<? extends EsmRowJFX>> finalTasksList =
        FXCollections.observableArrayList();
getRoot().getChildren().forEach(esmCore -> {
      ObservableList<TreeItem<EsmRowJFX>> treeItemTasks = esmCore.getChildren();
      ObservableList<EsmRowJFX> tasksList = EasyBind.map(treeItemTasks,TreeItem::getValue); //TreeItem::getValue is NOT the extractor logic code!
// I tried EasyBind.mapBacked instead of EasyBind.map and the result behavior is the same!
      finalTasksList.add(tasksList);
});

ObservableList<EsmRowJFX> list = EasyBind.flatten(finalTasksList);
setAllTasks(list); // set the list to the Class property: ObjectProperty<ObservableList<EsmRowJFX>>

I could attempt to write a unit test to generalize the example, if you think this type of feature can be implemented within EasyBind ?!

Could you point me to a unit test example that could speed up my process?

If treeItemTasks doesn't raise a change event when one of the items in this list is changed then there there is nothing we can do on the side of EasyBind. I'm not that familiar with TreeItem, but I guess you can inherit from it and overwrite the getChildren method to return a list with the proper extractor.

commented

You are right!

Extending the TreeItem would be quite complex since I will have to overwrite the private ObservableList<TreeItem<T>> children and also overwrite all the private methods that used that children member.

I will close the issue. Thanks for your feedback!