Select tree component with checkbox recursively down and up

Hello everyone, would it be possible for the Tree component to have checkbox that when selecting a branch all your children also did? Would be to use it in the same way that Cuba Studio uses it. It would be fantastic to be able to use it also in the Tree Table component.
Greetings and thanks.

Hello, the best variant is to use WidgetsTree.

I’ll use entity Employee to show how to do it.

You have to create new view which includes chief and subordinates. Also you can setup entity instance name in entity editor.

After that you should create screen with HierarchicalDatasource and WidgetsTree, which is linked to the datasource:


<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
        caption="msg://browseCaption"
        class="com.company.checkabletree.web.employee.EmployeeBrowse"
        messagesPack="com.company.checkabletree.web.employee">
    <dsContext>
        <hierarchicalDatasource id="employeesDs"
                                class="com.company.checkabletree.entity.Employee"
                                hierarchyProperty="chief"
                                view="employee-view">
            <query>
                <![CDATA[select e from checkabletree$Employee e]]>
            </query>
        </hierarchicalDatasource>
    </dsContext>
    <layout>
        <widgetsTree id="tree"
                     height="100%"
                     width="100%">
            <items datasource="employeesDs"></items>
        </widgetsTree>
    </layout>
</window>

Next step is to setup WidgetBuilder to generate rows in WidgetsTree.

In screen controller you should inject:

  1. WidgetsTree
  2. HierarchicalDatasource
  3. ComponentsFactory

public class EmployeeBrowse extends AbstractLookup {
    @Inject
    private ComponentsFactory componentsFactory;
    @Inject
    private HierarchicalDatasource<Employee, UUID> employeesDs;
    @Inject
    private WidgetsTree<Employee> tree;
    ...
}

and create new Map to store Employees linked to the CheckBoxes:


private Map<Employee, CheckBox> employeeCheckBoxMap = new HashMap<>();

Let’s setup our WidgetBuilder in overrided init method of controller:


@Override
public void init(Map<String, Object> params) {
    tree.setWidgetBuilder((datasource, itemId, leaf) -> {
        final Employee employee = employeesDs.getItem((UUID) itemId);
        if (employee == null)
            return null;

        CheckBox checkBox = (CheckBox) componentsFactory.createComponent(CheckBox.NAME);
        // entity instance name will be shown to the right of checkbox
        checkBox.setCaption(employee.getInstanceName());

        checkBox.addValueChangeListener(e -> {
            // update children
            for (Employee subordinate : employee.getSubordinates()) {
                updateRecursive(subordinate, (boolean) e.getValue());
            }
        });
        employeeCheckBoxMap.put(employee, checkBox);

        return checkBox;
    });
}

private void updateRecursive(Employee employee, boolean checked) {
    CheckBox checkBox = employeeCheckBoxMap.get(employee);
    checkBox.setValue(checked);

    for (Employee subordinate : employee.getSubordinates()) {
        updateRecursive(subordinate, checked);
    }
}

If you want to update parents you should use this code in CheckBox ValueChangeListener:


checkBox.addValueChangeListener(e -> {
    Employee chief = employee.getChief();
    if (chief != null) {
        updateRecursive(chief, (boolean) e.getValue());
    }
});

private void updateRecursive(Employee employee, boolean checked) {
    CheckBox checkBox = employeeCheckBoxMap.get(employee);
    checkBox.setValue(checked);

    Employee chief = employee.getChief();
    if (chief != null) {
        updateRecursive(chief, checked);
    }
}

And as result we will get a such screen:

employee

employee-view

employee-result

Thanks for your answer.
Greetings.

Hi Daniil,
Could you share this sample project about WidgetsTree, please? Is it same usage in Cuba6.10?

Hello @anjingjing

Unfortunately I don’t have the project anymore. Please ask me questions if you’ll encounter problems.

Regards,
Daniil

Hi Daniil,
Could you help check this issue: How to use widgetsTree component - #4 от пользователя 624517928 - CUBA.Platform
The WidgetsTree seems has data in it, but not display correctly. We are using cuba6.10 and halo theme.

As I see the problem is solved. Am I right?

Yes, never mind :blush:

1 Like