Skip to content

Latest commit

 

History

History
259 lines (197 loc) · 7.06 KB

File metadata and controls

259 lines (197 loc) · 7.06 KB

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