Vaadin újrafelhasználható felületi elemek

Fórumok

Most ismerkedek a Vaadinnal.Azt a feladatot kaptam, hogy alakítsak ki olyan kódbázist, amiben újra felhasználható elemek vannak.
Itt viszont állandó küzdés volt eddig.

A lényeg a kód, így mutatok példát:

public class AComponent extends VerticalLayout implements MyComponent {

    private static final String PERSON = "Személy";
    private static final String ORGANIZATION = "Szervezet";

    private ADto aDto = new ADto();

    private ComboBox<String> type = new ComboBox<>();

    private PersonComponent personComponent;

    private OrganizationComponent organizationComponent;

    private Binder<ADto> binder = new BeanValidationBinder<>(ADto.class);

    public AComponent(String title) {
        binder.forField(type).bind(ADto::getType, ADto::setType);
        //binder.bindInstanceFields(true);
        binder.setBean(aDto);

        add(new H3(title));
        setPadding(false);

        type.setPlaceholder("<válasszon>");
        type.setItems(PERSON, ORGANIZATION);
        add(type);

        VerticalLayout sumbitterDataContainer = new VerticalLayout();
        sumbitterDataContainer.setPadding(true);
        sumbitterDataContainer.setSpacing(false);
        add(sumbitterDataContainer);

        type.addValueChangeListener(listener -> {
            if (isPerson()) {
                personComponent = new PersonComponent(sumbitterDataContainer);
            } else {
                organizationComponent = new OrganizationComponent(sumbitterDataContainer);
            }
        });
    }

    @Override
    public boolean validate() {
        boolean valid = binder.validate().isOk();
        if (valid && isPerson()) {
            valid = personComponent.validate();
        }
        if (valid && isOrganization()) {
            valid = organizationComponent.validate();
        }

        return valid;
    }
    private boolean isOrganization() {
        return ORGANIZATION.equals(type.getValue());
    }

    private boolean isPerson() {
        return PERSON.equals(type.getValue());
    }
}

public class PersonComponent extends VerticalLayout implements MyComponent {

    private PersonDto personDto = new PersonDto();
    private NameComponent personName = new NameComponent("Viselt név");
    private NameComponent birthName = new NameComponent("Születési név");

    private Binder<PersonDto> binder = new BeanValidationBinder<>(PersonDto.class);

    public PersonComponent(FlexComponent container) {
        binder.bindInstanceFields(this);
        binder.setBean(personDto);

        addDataFields(container);
    }

    @Override
    public boolean validate() {
        return binder.isValid() && personName.validate() && birthName.validate();
    }

    private void addDataFields(final FlexComponent container) {
        container.removeAll();
        container.add(personName, birthName);
    }
}

public class PersonDto {
    private NameDto personName;
    private NameDto birthName;
    private NameDto mothersName;
    private BirthplaceDto birthplace;
    private LocalDate birthdate;
    // getters, setters...
}

public class ADto {

    @NotNull
    @NotEmpty
    @NotBlank
    @Size(min = 1)
    private String type;

    private PersonDto personDto;

    private OrganizationDto organizationDto;
    // getters, setters...
}

Azaz pl. van egy névbekérő rész ami ismétlődhet több formon is. 

Körülnéztem a Vaadin oldalán is, de csak egyszerű példák vannak. Ahol mindent feldobálsz egy form-ra, és nem használsz újra részeket. Kerestem Google-el is, de nem találtam komolyabb példákat.

1.) Az elképzelésem az volt, hogy A dto-kon levő annotációkkal tudom kontrollálni a felületen megjelenő hibaüzeneteket.
Tehát ha pl. kötelező megadni a AComponent type lenyílóját, ha pl. rákattint egy gombra amivel mentené a formot és validálja is közben a validate metódussal, akkor majd szépen kiírja a hibaüzenetet, hogy "nem lehet üres" a type mező alá. De ez nem történik meg. :( Látható, hogy ráraktam szinte minden létező annotációt. De a binder.isValid() azt mondja valid, amikor null az értéke.

2.) Valamint eredetileg arra gondoltam, hogy biztos van valami automatizáció, amely egy ilyen Component tree-n végig tud menni és a bevitt adatokból létrehoz egy ADto-t, benne a PersonDto-val, benne a NameDto-kkal stb. Úgy tűnik ilyen nincs. :(

Az is lehet csak rossz helyen kutatok és van valami egyszerű megoldás is, ami működik is.
Van valakinek valami megoldása erre?

Hozzászólások

Az 1.)-re megvan a megoldás. Mivel az automatikus bind nem működött, ezért a bind-nak nekem kell megadnom a validátort. Így működik, bár így elég össze-vissza lesz minden, hiszen egyszer a dto-kban számít ha van rajta annotáció, máskor nem.

A 2)-at megoldom akkor, hogy végig megyek a component tree-n, de ház ez is elég gáz, hogy itt is vegyesen lesz a bind.

Elég gányolt lesz így a kód. Aminek nem örülök. :( 

Nem szeretnék külön  frameworkot fejleszteni fölé. Egyszerűen csak újra felhasználható form részeket szeretnék, pl. a példában a névre. Ahol a név több mezőből állhat. Ezért kerestem volna valakit, aki nap mint nap használja, hátha van valami ami nincs a tutorialokban, de van értelmes megoldás.

Ami feltűnt, hogy nem jó a komponenesek átgondoltsága sem. Pl. ha több checkbox-od van és mindegyik kötelező, akkor egyenként bele kell rakni egy-egy CheckboxGroup-ba, hogy normálisan megjelenjen mellettük a kis piros hibaüzenet. Ez az egész framework ilyennek tűnik. Azaz nem gondolták át jól a fejlesztők mire lehet igény.

Hidd el, én is csodálkoztam, hogy ilyen alapvető gondok vannak. Ráadásul többször felmerült igény a checkbox-oknál a felhasználók részéről. Egyszer még MR-t is adott fel rá valaki. Ha pl. erre rákeresel a neten. akkor 2 féle megoldást kapsz: 1. saját megoldás készítése ( https://github.com/vaadin/flow-components/issues/3397 - ezt kipróbáltam - voltak vele hibák pl. a hibaüzenet eltűnt, ha kattintottál valahova az oldalon).  2. A checkboxgroup-os megoldás - ez egyelőre működik.