Overslaan naar hoofdinhoud

Validating and Binding Data

Openen in ChatGPT

Uw app van Observers and Route Parameters kan FormView gebruiken om bestaande klantgegevens te bewerken. Deze stap maakt gebruik van Data binding, wat UI-componenten rechtstreeks verbindt met het datamodel voor automatische waarde-synchronisatie. Dit vermindert boilerplate in uw app en stelt u in staat om validatiecontroles toe te voegen aan de Spring-entiteit Customer, waardoor uw gebruikers volledige en nauwkeurige informatie kunnen verstrekken bij het invullen van formulieren. Deze stap behandelt de volgende concepten:

Het voltooien van deze stap creëert een versie van 5-validating-and-binding-data.

De app uitvoeren

Terwijl u uw app ontwikkelt, kunt u 5-validating-and-binding-data gebruiken als vergelijking. Om de app in actie te zien:

  1. Navigeer naar de bovenste directory met het pom.xml-bestand, dit is 5-validating-and-binding-data als u de versie op GitHub volgt.

  2. Gebruik de volgende Maven-opdracht om de Spring Boot-app lokaal uit te voeren:

    mvn

Het uitvoeren van de app opent automatisch een nieuwe browser op http://localhost:8080.

Het definiëren van validatieregels

Het ontwikkelen van een app met bewerkbare gegevens moet validatie omvatten. Validatiecontroles helpen zinvolle en nauwkeurige door gebruikers ingediende gegevens te behouden. Als dit niet wordt gecontroleerd, kan dit tot problemen leiden, daarom is het belangrijk om de soorten fouten die gebruikers kunnen maken bij het invullen van een formulier in realtime op te vangen.

Aangezien wat als geldig wordt beschouwd kan verschillen tussen eigenschappen, moet u definiëren wat elke eigenschap geldig maakt en de gebruiker informeren als er iets ongeldig is. Gelukkig kunt u dit eenvoudig doen met Jakarta Validation. Jakarta-validatie stelt u in staat om beperkingen aan eigenschappen toe te voegen als annotaties.

Deze tutorial gebruikt twee Jakarta-annotaties, @NotEmpty en @Pattern. @NotEmpty controleert op null en lege strings, terwijl @Pattern controleert of de eigenschap overeenkomt met een reguliere expressie die u instelt. Beide annotaties stellen u in staat om een bericht toe te voegen dat wordt weergegeven wanneer de eigenschap ongeldig wordt.

Om te vereisen dat zowel voor- als achternaam verplicht zijn en alleen letters bevatten, terwijl de bedrijfsnaam optioneel is en letters, cijfers en spaties toestaat, past u de volgende annotaties toe op de entiteit Customer:

Customer.java

@NotEmpty(message = "Voornaam klant is vereist")
@Pattern(regexp = "[a-zA-Z]*", message = "Ongeldige tekens")
private String firstName = "";

@NotEmpty(message = "Achternaam klant is vereist")
@Pattern(regexp = "[a-zA-Z]*", message = "Ongeldige tekens")
private String lastName = "";

@Pattern(regexp = "[a-zA-Z0-9 ]*", message = "Ongeldige tekens")
private String company = "";

private Country country = Country.UNKNOWN;

public enum Country {
UNKNOWN,

Zie de Jakarta Bean Validation constraints reference voor een volledige lijst van validaties, of leer meer in het webforJ Jakarta Validation-artikel.

De velden binden

Om de validatiecontroles in Customer voor de UI in FormView te gebruiken, maakt u een BindingContext voor databinding. Voor databinding vereiste elk veld in FormView een evenementlistener om handmatig met een Spring-entiteit Customer te synchroniseren. Het maken van een BindingContext in FormView bindt en synchroniseert automatisch het datamodel Customer met de UI-componenten.

Een BindingContext maken

Een instantie van BindingContext heeft de Spring-bean nodig waarmee de bindingen zijn gesynchroniseerd. In FormView declareert u een BindingContext met de entiteit Customer:

FormView.java
public class FormView extends Composite<Div> implements WillEnterObserver {
private final CustomerService customerService;

private BindingContext<Customer> context;

Customer customer = new Customer();

Vervolgens, om UI-componenten automatisch te binden aan bean-eigenschappen op basis van hun namen, gebruikt u BindingContext.of() met de volgende parameters:

  • this : Eerder heeft u context gedeclareerd als de BindingContext. De eerste parameter stelt in welk object de bindbare componenten zich bevinden.
  • Customer.class : De tweede parameter is de klasse van de bean die voor binding moet worden gebruikt.
  • true : De derde parameter schakelt Jakarta-validatie in, waardoor de context de validaties die u hebt ingesteld voor Customer kan gebruiken. Dit zal de stijl van ongeldige componenten wijzigen en de ingestelde berichten weergeven.

Alles samen ziet het eruit als de volgende regel code:

context = BindingContext.of(this, Customer.class, true);

Formulier responsief maken

Met databinding voert uw app nu automatisch validatiecontroles uit. Door een evenementlistener aan de controles toe te voegen, kunt u voorkomen dat gebruikers een ongeldig formulier indienen. Voeg het volgende toe om de verzendknop alleen actief te maken wanneer het formulier geldig is:

context = BindingContext.of(this, Customer.class, true);
context.onValidate(e -> submit.setEnabled(e.isValid()));

Evenementlisteners voor componenten verwijderen

Elke UI-wijziging is nu automatisch gesynchroniseerd met de BindingContext. Dit betekent dat u nu de evenementlisteners voor elk veld kunt verwijderen:

Voor

FormView.java
// Zonder databinding
TextField firstName = new TextField("Voornaam", e -> customer.setFirstName(e.getValue()));
TextField lastName = new TextField("Achternaam", e -> customer.setLastName(e.getValue()));
TextField company = new TextField("Bedrijf", e -> customer.setCompany(e.getValue()));
ChoiceBox country = new ChoiceBox("Land",
e -> customer.setCountry(Country.valueOf(e.getSelectedItem().getText())));

Na

FormView.java
// Met databinding
TextField firstName = new TextField("Voornaam");
TextField lastName = new TextField("Achternaam");
TextField company = new TextField("Bedrijf");
ChoiceBox country = new ChoiceBox("Land");

Binden op basis van eigenschapsnamen

Aangezien de naam van elke component overeenkomt met het datamodel, heeft webforJ Automatische Binding toegepast. Als de namen niet overeenkwamen, kunt u de annotatie @UseProperty gebruiken om ze te koppelen.

@UseProperty("firstName")
TextField firstNameField = new TextField("Voornaam");

Gegevens lezen in de fillForm()-methode

Eerder initieerde u in de fillForm()-methode elke componentwaarde door handmatig de gegevens van de kopie van Customer op te halen. Maar nu, omdat u een BindingContext gebruikt, kunt u de read()-methode gebruiken. Deze methode vult elke gebonden component met de bijbehorende eigenschap uit de gegevens in de kopie van Customer.

In de fillForm()-methode vervangt u de setValue()-methoden door read():

FormView.java
public void fillForm(Long customerId) {
customer = customerService.getCustomerByKey(customerId);

// Verwijderde elke setValue() methode voor de UI-componenten

context.read(customer);
}

Validatie toevoegen aan submitCustomer()

De laatste wijziging in FormView voor deze stap zal een beveiliging toevoegen aan de submitCustomer()-methode. Voordat wijzigingen aan de H2-database worden doorgevoerd, voert de app een laatste validatie uit op de resultaten van de gebonden context met behulp van de write()-methode.

De write()-methode werkt de eigenschappen van een bean bij met behulp van de gebonden UI-componenten in de BindingContext en retourneert een ValidationResult.

Gebruik de write()-methode om naar de kopie van Customer te schrijven met behulp van de gebonden componenten in FormView. Als het geretourneerde ValidationResult geldig is, werk dan de H2-database bij met de geschreven gegevens.

FormView.java
private void submitCustomer() {
ValidationResult results = context.write(customer);
if (results.isValid()) {
if (customerService.doesCustomerExist(customerId)) {
customerService.updateCustomer(customer);
} else {
customerService.createCustomer(customer);
}
navigateToMain();
}
}

Voltooid FormView

Met deze wijzigingen ziet FormView er als volgt uit. De app ondersteunt nu databinding en validatie met behulp van Spring Boot en webforJ. Formuliervelden worden automatisch gesynchroniseerd met het model en gecontroleerd op validatieregels.

FormView.java
@Route("customer/:id?<[0-9]+>")
@FrameTitle("Klantformulier")
public class FormView extends Composite<Div> implements WillEnterObserver {
private final CustomerService customerService;
private BindingContext<Customer> context;
private Customer customer = new Customer();
private Long customerId = 0L;
private Div self = getBoundComponent();
private TextField firstName = new TextField("Voornaam");
private TextField lastName = new TextField("Achternaam");
private TextField company = new TextField("Bedrijf");
private ChoiceBox country = new ChoiceBox("Land");
private Button submit = new Button("Indienen", ButtonTheme.PRIMARY, e -> submitCustomer());
private Button cancel = new Button("Annuleren", ButtonTheme.OUTLINED_PRIMARY, e -> navigateToMain());
private ColumnsLayout layout = new ColumnsLayout(

Volgende stap

De volgende stap, Integrating an App Layout, richt zich op het gebruik van een AppLayout om een zijmenu toe te voegen dat beschikbaar is voor gebruikers op zowel de klantentabel als de klantformulierenpagina's. U leert ook over een ander lay-out hulpmiddel, de FlexLayout-component.