CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-vaadin--vaadin-core

Vaadin Platform (vaadin-core) - Core component of the Vaadin web framework platform

Overview
Eval results
Files

data-integration.mddocs/

Data Integration

Data binding and providers for connecting UI components to backend data sources.

Quick links: Binder | DataProvider | Hierarchical DataProvider | Renderers

Related components: Grid (see Components), ComboBox (see Components)

Binder

Two-way data binding between UI components and Java beans.

class Binder<BEAN> {
    Binder();
    Binder(Class<BEAN> beanType);
    <FIELDVALUE> BindingBuilder<BEAN, FIELDVALUE> forField(HasValue<?, FIELDVALUE> field);
    void setBean(BEAN bean);
    void readBean(BEAN bean);
    boolean writeBeanIfValid(BEAN bean) throws ValidationException;
    BinderValidationStatus<BEAN> validate();
}

interface BindingBuilder<BEAN, FIELDVALUE> {
    BindingBuilder<BEAN, FIELDVALUE> withValidator(Validator<? super FIELDVALUE> validator);
    BindingBuilder<BEAN, FIELDVALUE> asRequired(String errorMessage);
    <NEWTARGET> BindingBuilder<BEAN, NEWTARGET> withConverter(Converter<FIELDVALUE, NEWTARGET> converter);
    Binding<BEAN, FIELDVALUE> bind(ValueProvider<BEAN, FIELDVALUE> getter,
                                    Setter<BEAN, FIELDVALUE> setter);
    Binding<BEAN, FIELDVALUE> bind(String propertyName);
}

interface Validator<T> {
    ValidationResult apply(T value, ValueContext context);
}

Examples:

Binder<Person> binder = new Binder<>(Person.class);

TextField firstName = new TextField("First Name");
binder.forField(firstName)
    .asRequired("Required")
    .withValidator(name -> name.length() >= 2, "Min 2 characters")
    .bind(Person::getFirstName, Person::setFirstName);

EmailField email = new EmailField("Email");
binder.forField(email)
    .asRequired("Required")
    .bind(Person::getEmail, Person::setEmail);

// Load data
binder.setBean(person);

// Save data
if (binder.writeBeanIfValid(person)) {
    personService.save(person);
    Notification.show("Saved");
}

DataProvider

Interface for providing data to components like Grid and ComboBox.

interface DataProvider<T, F> {
    Stream<T> fetch(Query<T, F> query);
    int size(Query<T, F> query);
    void refreshItem(T item);
    void refreshAll();
    static <T> ListDataProvider<T> ofCollection(Collection<T> items);
    static <T, F> DataProvider<T, F> fromCallbacks(
        CallbackDataProvider.FetchCallback<T, F> fetchCallback,
        CallbackDataProvider.CountCallback<T, F> countCallback);
}

class ListDataProvider<T> implements DataProvider<T, SerializablePredicate<T>> {
    ListDataProvider(Collection<T> items);
    void setFilter(SerializablePredicate<T> filter);
    void setSortOrder(ValueProvider<T, ?> valueProvider, SortDirection direction);
}

class Query<T, F> {
    int getOffset();
    int getLimit();
    List<QuerySortOrder> getSortOrders();
    Optional<F> getFilter();
}

abstract class AbstractBackEndDataProvider<T, F> implements DataProvider<T, F> {
    protected abstract Stream<T> fetchFromBackEnd(Query<T, F> query);
    protected abstract int sizeInBackEnd(Query<T, F> query);
}

Examples:

// Grid with DataProvider
Grid<Customer> grid = new Grid<>(Customer.class);
grid.setColumns("name", "email");

DataProvider<Customer, Void> dataProvider = DataProvider.fromCallbacks(
    query -> {
        int offset = query.getOffset();
        int limit = query.getLimit();
        List<QuerySortOrder> sortOrders = query.getSortOrders();
        return customerService.fetch(offset, limit, sortOrders).stream();
    },
    query -> customerService.count()
);
grid.setDataProvider(dataProvider);

// ListDataProvider with filtering
ListDataProvider<Product> listProvider = DataProvider.ofCollection(products);
TextField searchField = new TextField();
searchField.addValueChangeListener(e -> {
    String term = e.getValue().toLowerCase();
    listProvider.setFilter(p -> p.getName().toLowerCase().contains(term));
});
grid.setDataProvider(listProvider);

Hierarchical DataProvider

For tree structures like TreeGrid.

interface HierarchicalDataProvider<T, F> extends DataProvider<T, F> {
    int getChildCount(HierarchicalQuery<T, F> query);
    boolean hasChildren(T item);
}

abstract class AbstractBackEndHierarchicalDataProvider<T, F>
        implements HierarchicalDataProvider<T, F> {
    protected abstract Stream<T> fetchChildrenFromBackEnd(HierarchicalQuery<T, F> query);
    public abstract int getChildCount(HierarchicalQuery<T, F> query);
    public abstract boolean hasChildren(T item);
}

Example:

TreeGrid<Department> treeGrid = new TreeGrid<>();
treeGrid.addHierarchyColumn(Department::getName);

HierarchicalDataProvider<Department, Void> provider =
    new AbstractBackEndHierarchicalDataProvider<Department, Void>() {
        @Override
        protected Stream<Department> fetchChildrenFromBackEnd(
                HierarchicalQuery<Department, Void> query) {
            Department parent = query.getParent();
            return parent == null ?
                departmentService.fetchRoots(query.getOffset(), query.getLimit()).stream() :
                departmentService.fetchChildren(parent, query.getOffset(), query.getLimit()).stream();
        }

        @Override
        public int getChildCount(HierarchicalQuery<Department, Void> query) {
            Department parent = query.getParent();
            return parent == null ?
                departmentService.countRoots() :
                departmentService.countChildren(parent);
        }

        @Override
        public boolean hasChildren(Department item) {
            return departmentService.hasChildren(item);
        }
    };
treeGrid.setDataProvider(provider);

Renderers

class ComponentRenderer<C extends Component, T> implements Renderer<T> {
    ComponentRenderer(SerializableFunction<T, C> componentProvider);
    ComponentRenderer(SerializableFunction<T, C> componentProvider,
                     SerializableConsumer<C> componentUpdater);
}

class LitRenderer<T> implements Renderer<T> {
    static <T> LitRenderer<T> of(String template);
    LitRenderer<T> withProperty(String property, ValueProvider<T, ?> provider);
}

Examples:

Grid<Product> grid = new Grid<>();
grid.addColumn(new ComponentRenderer<>(product ->
    new HorizontalLayout(
        new Image(product.getImageUrl(), ""),
        new Span(product.getName())
    )
));

grid.addColumn(LitRenderer.<Product>of("<b>[[item.name]]</b><br><small>[[item.description]]</small>")
    .withProperty("name", Product::getName)
    .withProperty("description", Product::getDescription));

Install with Tessl CLI

npx tessl i tessl/maven-com-vaadin--vaadin-core

docs

advanced.md

components.md

core-framework.md

data-integration.md

index.md

layouts.md

security.md

themes-styling.md

tile.json