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?