Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

298 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Published on Vaadin Directory Stars on Vaadin Directory Latest version on vaadin.com/directory

Crud UI Add-on provides a fluent, type-safe API to generate CRUD UIs for Java beans in Vaadin.

The main entrypoint is Crud.of(YourBean.class), which starts with sensible defaults:

  • List: GridList
  • Layout: SplitCrudLayout
  • Form factory: AutoGeneratedFormFactory

For questions, use the forum thread: https://vaadin.com/forum/t/crud-ui-add-on/156634/1

Requirements

  • Java 21+
  • Vaadin 25.2.3
  • Maven

Quick Start

Minimal CRUD with defaults (no actual backend operations are performed):

Crud<User> crud = Crud.of(User.class).build();
add(crud);

CRUD wired to backend operations:

Crud<User> crud = Crud.of(User.class)
    .onCreate(userService::save)
    .onRead(userService::findAll)
    .onUpdate(userService::save)
    .onDelete(userService::delete)
    .build();

add(crud);

Core API

Crud<B> is a Vaadin component (Composite<VerticalLayout>) with a fluent builder API:

  • Crud.of(Class<B>)
  • onCreate(Consumer<B>)
  • onRead(Supplier<? extends Collection<B>>)
  • onRead(DataProvider<B, ?>)
  • onUpdate(Consumer<B>)
  • onDelete(Consumer<B>)
  • list(CrudListFactory<B>)
  • layout(CrudLayoutFactory<B>)
  • form(CrudFormFactory<B>)
  • build()

Main contracts:

  • CrudLayout<B>: how list + form are arranged in the UI
  • CrudList<B>: list abstraction (selection, refresh, data provider)
  • CrudForm<B>: form abstraction (value/read-only/validation)
  • CrudFormFactory<B>: factory for operation-specific forms

Read Operations

You can wire reads using either a collection supplier or a DataProvider.

Collection Supplier

Crud<User> crud = Crud.of(User.class)
    .onRead(userService::findAll)
    .build();

Lazy/Paginated DataProvider

Crud<User> crud = Crud.of(User.class)
    .onRead(DataProvider.fromCallbacks(
        query -> userService.findByNameContainingIgnoreCase(
            filterValue, query.getPage(), query.getPageSize()).stream(),
        query -> (int) userService.countByNameContainingIgnoreCase(filterValue)
    ))
    .build();

Layout Customization

Split Layout (default)

Crud<User> crud = Crud.of(User.class)
    .layout(SplitCrudLayout.of(User.class)
        .orientation(Orientation.HORIZONTAL))
    .build();

Dialog Layout

Crud<User> crud = Crud.of(User.class)
    .layout(DialogCrudLayout.of(User.class)
        .dialogWidth("60vw")
        .dialogResizable(true))
    .build();

List Customization

Use your own configured Grid and plug it into GridList:

Grid<User> grid = new Grid<>();
grid.addColumn(User::getId).setHeader("ID");
grid.addColumn(User::getName).setHeader("Name");
grid.addColumn(User::getEmail).setHeader("Email");

Crud<User> crud = Crud.of(User.class)
    .list(GridList.of(User.class).grid(grid))
    .onCreate(userService::save)
    .onRead(userService::findAll)
    .onUpdate(userService::save)
    .onDelete(userService::delete)
    .build();

Form Customization

AutoGeneratedFormFactory supports operation-specific fields and fluent field configuration.

Crud<User> crud = Crud.of(User.class)
    .form(AutoGeneratedFormFactory.of(User.class)
        .fields(
            Field.of(User::getName, User::setName, String.class).label("Name"),
            Field.of(User::getEmail, User::setEmail, String.class).label("Email"),
            Field.of(User::getActive, User::setActive, Boolean.class).label("Active")
        )
        .fieldsFor(CrudOperation.CREATE,
            Field.of(User::getName, User::setName, String.class).label("Name"),
            Field.of(User::getEmail, User::setEmail, String.class).label("Email"),
            Field.of(User::getPassword, User::setPassword, String.class).label("Password")
        )
        .useBeanValidation()
        .captions("Create user", "Edit user"))
    .build();

Other useful methods:

  • additionalFieldsFor(CrudOperation, Field.Builder...)
  • replace(propertyName, Field.Builder)

Behavior and UX Options

View-before-edit mode

Show selected items read-only first, then edit after clicking Update:

Crud<User> crud = Crud.of(User.class)
    .viewBeforeEdit(true)
    .build();

Operation visibility

Crud<User> crud = Crud.of(User.class)
    .createOperationVisible(true)
    .updateOperationVisible(true)
    .deleteOperationVisible(false)
    .build();

Custom new instance supplier

Crud<User> crud = Crud.of(User.class)
    .form().newInstanceSupplier(() -> {
        User user = new User();
        user.setActive(true);
        return user;
    })
    .build();

Filter components

TextField nameFilter = new TextField();
nameFilter.setPlaceholder("Search by name...");

Crud<User> crud = Crud.of(User.class)
    .addFilterComponent(nameFilter)
    .onRead(dataProvider)
    .build();

Button and Dialog Customization

Customize action buttons by CRUD operation:

Crud<User> crud = Crud.of(User.class)
    .button(CrudOperation.CREATE).label("New", VaadinIcon.PLUS::create)
    .button(CrudOperation.UPDATE).variants(ButtonVariant.LUMO_PRIMARY)
    .button(CrudOperation.DELETE).label("Remove", VaadinIcon.TRASH::create, ButtonVariant.LUMO_ERROR)
    .build();

Customize delete confirmation text:

Crud<User> crud = Crud.of(User.class)
    .deleteConfirmation().texts(
        "Delete user?",
        "This operation cannot be undone.",
        "Delete",
        "Cancel"
    )
    .onDelete(userService::delete)
    .build();

Success/Error Hooks

Crud<User> crud = Crud.of(User.class)
    .onSaveSuccess(saved -> Notification.show("Saved: " + saved.getName()))
    .onDeleteSuccess(deleted -> Notification.show("Deleted: " + deleted.getName()))
    .onOperationError(error -> Notification.show("Operation failed: " + error.getMessage()))
    .build();

Legacy API Migration Notes

If you are upgrading from older version of CrudUI Add-On, use this mapping:

Legacy usage Current usage
new GridCrud<>(User.class) Crud.of(User.class).build()
setFindAllOperation(...) onRead(...)
setAddOperation(...) onCreate(...)
setUpdateOperation(...) onUpdate(...)
setDeleteOperation(...) onDelete(...)
CrudListener / LazyCrudListener wiring Fluent onCreate/onRead/onUpdate/onDelete methods
DefaultCrudFormFactory old API methods AutoGeneratedFormFactory.of(...).fields(...).fieldsFor(...).useBeanValidation()

Examples in This Repository

  • Basic: crud-ui-demo/src/main/java/org/vaadin/crudui/demo/ui/view/DefaultView.java
  • Advanced: crud-ui-demo/src/main/java/org/vaadin/crudui/demo/ui/view/CustomizedView.java

License

Apache License 2.0

About

Automatically generate CRUD-like Vaadin views for any Java Bean

Topics

Resources

Stars

100 stars

Watchers

14 watching

Forks

Releases

Packages

Used by

Contributors

Languages