Adding vaadin component on browseWindow

Hi

How can I easily add a vaadin component to browserWindow ? I want to use tree component.

hi,

why do you need a vaadin component for that? In case of a tree you can use the CUBA tree component - https://demo.cuba-platform.com/sampler/open?screen=simple-tree, correct?

Bye
Mario

See also Working with Vaadin Components.

Hi

I need tree component doesn’t associate with dataset and entites. I’d like to create two level tree. First level will be represent years, second month of the year.

Hi,

the Tree component only needs to have a hierachical datasource to work. It does not necessarily be persistent entities. It can also be non persistent entities. Also a CustomValueHierarchicalDatasource is possible, then you don’t even need a entity at all but rather can work with KeyValueEntities.

Bye

Then, I may to set datasource by setDatasource method in Tree class in java code.
Have you got any example, how can I create hierarchicalDatasource ?

Use DsBuilder. It has a fluent interface with different terminal methods creating different types of datasources, for example buildHierarchicalDatasource() or buildValuesHierarchicalDatasource().

ok I create method like bellow. From can I get datasourceClass ?
Entity Month is not persistent. How can I add items to this datasource ?

private void ceratePeriodDs() {
	Entity<Months> month = dataSupplier.newInstance(metadata.getClassNN(Months.class));
	HierarchicalDatasource<Entity<Months>, Months> optionsDatasource = DsBuilder.create()
			.setMetaClass(month.getMetaClass()).setViewName(View.MINIMAL).buildValuesHierarchicalDatasource(datasourceClass);
	optionsDatasource.setHierarchyPropertyName("parentId");

}

Hi,

here’s a running example:

cuba-example-non-persistent-tree.zip (83.2 KB)

The Datasource class:

public class YearMonthDatasource extends CustomHierarchicalDatasource<YearMonth, UUID> {
@Override
protected Collection<YearMonth> getEntities(Map<String, Object> params) {

    Collection<YearMonth> yearMonths = new ArrayList<>();

    for (int year = 2000; year < 2030; year++) {

        YearMonth yearToAdd = createYear(year);
        yearMonths.add(yearToAdd);

        for (int month = 1; month < 13; month++) {
            YearMonth monthToAdd = createMonth(yearToAdd, month);
            yearMonths.add(monthToAdd);
        }

    }


    return yearMonths;
}

private YearMonth createYear(int year) {
    YearMonth yearToAdd = getMetadata().create(YearMonth.class);
    yearToAdd.setValue(String.format("%4d", year));
    return yearToAdd;
}

private YearMonth createMonth(YearMonth parent, int value) {
    YearMonth monthToAdd = getMetadata().create(YearMonth.class);
    monthToAdd.setValue(parent.getValue() + " / " + value);
    monthToAdd.setParent(parent);
    return monthToAdd;
}

private Metadata getMetadata() {
    return AppBeans.get(Metadata.NAME);
}

}

The screen XML:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
    caption="msg://caption"
    class="com.company.cenpt.web.screens.YearMonthExample"
    messagesPack="com.company.cenpt.web.screens">
<dsContext>
    <hierarchicalDatasource id="yearMonthDs"
                            class="com.company.cenpt.entity.YearMonth"
                            datasourceClass="com.company.cenpt.web.screens.YearMonthDatasource"
                            hierarchyProperty="parent"/>
</dsContext>
<dialogMode height="600"
            width="800"/>
<layout>
    <tree height="300px"
          id="yearMonthTree"
          width="100%">
        <treechildren datasource="yearMonthDs"/>
    </tree>
</layout>
</window>

And the controller:

public class YearMonthExample extends AbstractWindow {

@Inject
protected YearMonthDatasource yearMonthDs;


@Inject
protected Tree<YearMonth> yearMonthTree;

@Override
public void ready() {
    super.ready();

    yearMonthTree.setItemClickAction(new BaseAction("itemClicked") {
        @Override
        public void actionPerform(Component component) {
            YearMonth yearMonth = yearMonthTree.getSingleSelected();

            if (yearMonth != null) {

                showNotification("" + yearMonth.getValue(), NotificationType.TRAY);
            }

        }
    });
}
}

The result looks like this:
22

I hope this helps a little.

Bye
Mario

1 Like

Great thanks for example Mario !!

Hi

I have last problem. I’d like to expand current year level. I do it in browse controler in init method like bellow, but yearMonthDs.getItems() return empty collection. Why have I empty collection ?

public class RentalPositionBrowse extends AbstractLookup {

@Inject
private GroupTable<RentalPosition> rentalPositionsTable;
@Inject
private GroupDatasource<RentalPosition, Integer> rentalPositionsDs;
@Inject
private UserSettingService userSettingService;

@Inject
private Tree yearMonthTree;

@Inject
protected HierarchicalDatasource<Periods, UUID> yearMonthDs;

@SuppressWarnings("unchecked")
@Override
public void init(Map<String, Object> params) {
	// TODO Auto-generated method stub
	super.init(params);
	addRentalPositionsStyleProvider();
	addCustomAction();
	Periods curr = null;
	Date currDate = new Date();
	
	final Collection<Periods> items = yearMonthDs.getItems();

	for (Periods p : items) {
		if (p.getParent() == null) {
			if ((currDate.getTime() >= p.getStartDate().getTime())
					&& (currDate.getTime() <= p.getEndDate().getTime())) {
				curr = p;
				break;
			}
		}
	}
	if (curr != null) {
		yearMonthTree.expand(curr);
		yearMonthTree.setSelected(curr);
	}

}

Blockquote

Hi,

In init the declarative datasources are not filled yet.

Push the logic to the ready method hook.

Bye
Mario

Hi

I move my code to the ready method, but I have empty collection still.

public class RentalPositionBrowse extends AbstractLookup {

@Inject
private GroupTable<RentalPosition> rentalPositionsTable;
@Inject
private GroupDatasource<RentalPosition, Integer> rentalPositionsDs;
@Inject
private UserSettingService userSettingService;

@Inject
private Tree yearMonthTree;

@Inject
protected HierarchicalDatasource<Periods, UUID> yearMonthDs;

@SuppressWarnings("unchecked")
@Override
public void ready() {
	// TODO Auto-generated method stub
	super.ready();
	Periods curr = getCurrentYear(yearMonthDs.getItems());
	if (curr != null) {
		yearMonthTree.expand(curr);
		yearMonthTree.setSelected(curr);
	}

}

private Periods getCurrentYear(Collection<Periods> items) {
	Periods curr = null;
	Date currDate = new Date();
	for (Periods p : items) {
		if (p.getParent() == null) {
			if ((currDate.getTime() >= p.getStartDate().getTime())
					&& (currDate.getTime() <= p.getEndDate().getTime())) {
				curr = p;
				break;
			}
		}

	}
	return curr;
}

Blockquote

hi,

i think you have to share a complete example project. Then it will be easier to help you.

Bye
Mario

Hi

I attach project. You have to swich to english version. Controler name RentalPositionBrowserental.zip (11.9 MB)

ok.
I resolved this problem myself. I used yearMonthDs.refresh() before getting items from collection.
I expect then better way to do it by pluggable component factories, but this facility needs fieldGroup
component. Maybe there is any way to do it.