Passer au contenu principal

Transformation

Ouvrir dans ChatGPT

Les transformations de données convertissent les types de données utilisés dans les composants de l'interface utilisateur et ceux de votre modèle de données. Cela maintient les types de données compatibles et correctement formatés lors du déplacement des données entre le frontend et le backend de vos applications.

conseil

Le paramètre du transformateur est mieux utilisé lorsque le type de données de la propriété bean ne correspond pas au type de données géré par les composants de l'interface utilisateur. Si vous avez simplement besoin de transformer des données du même type, configurer les getters et setters de liaisons est l'approche préférée.

Configuration des transformateurs

Vous configurez les transformations de données directement au sein de vos liaisons, vous permettant ainsi de définir comment les données doivent être transformées pendant le processus de liaison de données.

Vous pouvez ajouter des transformateurs à une liaison en utilisant la méthode useTransformer sur le BindingBuilder. Les transformateurs doivent implémenter l'interface Transformer, qui nécessite de définir des méthodes pour les deux directions du flux de données : du modèle vers l'UI et de l'UI vers le modèle.

context.bind(salaryField, "salary")
.useTransformer(new CurrencyTransformer())
.add();

Dans l'exemple ci-dessus, le code configure un CurrencyTransformer pour gérer les conversions entre le type de données du modèle (par exemple, BigDecimal) et la représentation de l'UI (par exemple, une chaîne formatée).

info

Chaque liaison est associée à un seul transformateur. Si la transformation d'une valeur nécessite plusieurs étapes, il est conseillé de mettre en œuvre votre propre transformateur pour ces étapes.

Implémentation d'un transformateur

Voici un exemple d'implémentation d'un transformateur simple qui convertit entre un modèle LocalDate et une représentation UI String :

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import com.webforj.data.transformation.TransformationException;
import com.webforj.data.transformation.transformer.Transformer;

public class DateTransformer implements Transformer<LocalDate, String> {
private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

@Override
public LocalDate transformToComponent(String modelValue) {
try {
return LocalDate.parse(modelValue, formatter);
} catch (Exception e) {
throw new TransformationException("Format de date invalide");
}
}

@Override
public String transformToModel(LocalDate componentValue) {
try {
return componentValue.format(formatter);
} catch (Exception e) {
throw new TransformationException("Format de date invalide");
}
}
}

Ce transformateur gère les champs de date, en formatant les dates lorsqu'elles sont affichées dans l'UI et en les analysant à nouveau dans le modèle.

Utilisation des transformateurs dans les liaisons

Une fois que vous avez défini un transformateur, vous pouvez l'appliquer à plusieurs liaisons dans votre application. Cette approche est particulièrement utile pour les formats de données standard qui nécessitent un traitement cohérent à travers différentes parties de votre application.

BindingContext<Employee> context = new BindingContext<>(Employee.class);
context.bind(startDateField, "startDate", String.class)
.useTransformer(new DateTransformer())
.add();
Spécification du type de propriété Bean

Dans la méthode bind, il est essentiel de spécifier le type de la propriété bean en tant que troisième paramètre lorsqu'il y a une divergence entre le type de données affiché par le composant UI et le type de données utilisé dans le modèle. Par exemple, si le composant gère startDateField comme un LocalDate Java au sein du composant mais est stocké comme un String dans le modèle, définir explicitement le type comme String.class indique au mécanisme de liaison de traiter et de convertir correctement les données entre les deux types différents utilisés par le composant et le bean à l'aide du transformateur et des validateurs fournis.

Simplification des transformations avec Transformer.of

Il est possible de simplifier l'implémentation de telles transformations en utilisant la méthode Transformer.of fournie par le Transformer. Cette méthode est une syntaxe simplifiée et permet d'écrire une méthode qui gère les transformations directement, plutôt que de passer une classe implémentant l'interface Transformer.

Dans l'exemple suivant, le code gère une interaction de case à cocher dans une application de voyage où les utilisateurs peuvent opter pour des services supplémentaires comme la location de voiture. L'état de la case à cocher boolean doit être transformé en une représentation en chaîne "yes" ou "no" que le modèle backend utilise.

CheckBox carRental = new CheckBox("Location de voiture");
BindingContext<Trip> context = new BindingContext<>(Trip.class, true);
context.bind(carRental, "carRental", String.class)
.useTransformer(
Transformer.of(
// convertir la valeur du composant en valeur du modèle
bool -> Boolean.TRUE.equals(bool) ? "yes" : "no",
// convertir la valeur du modèle en valeur du composant
str -> str.equals("yes")
),

// en cas d'échec de la transformation, afficher le message suivant
// message
"La case à cocher doit être cochée"
)
.add();

Messages d'erreur de transformateur dynamiques 25.12

Par défaut, le message d'erreur affiché lorsque la transformation échoue est une chaîne statique. Dans les applications qui prennent en charge plusieurs langues, vous pouvez passer un Supplier<String> à la place, de sorte que le message soit résolu chaque fois que la transformation échoue :

context.bind(quantityField, "quantity", Integer.class)
.useTransformer(
Transformer.of(
str -> Integer.parseInt(str),
val -> String.valueOf(val)
),
() -> t("validation.quantity.invalid")
)
.add();

Le fournisseur est invoqué uniquement lorsque la transformation génère une TransformationException. Cela signifie que le message reflète toujours la locale actuelle au moment de l'échec.

Transformateurs sensibles à la locale

Pour les transformateurs réutilisables qui ont besoin d'accéder à la locale actuelle en interne (par exemple, pour formater des nombres ou des dates selon les conventions régionales), implémentez l'interface LocaleAware. Lorsque la locale change via BindingContext.setLocale(), le contexte propage automatiquement la nouvelle locale aux transformateurs qui implémentent cette interface.