Passer au contenu principal

Using Components

Ouvrir dans ChatGPT
Java API

Les composants sont les blocs de construction des applications webforJ. Que vous utilisiez des composants intégrés comme Button et TextField, ou que vous travailliez avec des composants personnalisés fournis par votre équipe, la manière dont vous interagissez avec eux suit le même modèle cohérent : vous configurez des propriétés, gérez l'état et combinez des composants dans des mises en page.

Ce guide se concentre sur ces opérations quotidiennes : pas sur les détails internes du fonctionnement des composants, mais sur la manière de les utiliser en pratique.

Propriétés du composant

Chaque composant expose des propriétés qui contrôlent son contenu, son apparence et son comportement. La plupart d'entre elles ont des méthodes Java typées dédiées (setText(), setTheme(), setExpanse(), etc.), qui constituent le principal moyen de configurer des composants dans webforJ. Les sections ci-dessous couvrent les propriétés et les méthodes qui s'appliquent de manière générale à tous les types de composants.

Contenu textuel

La méthode setText() définit le texte visible d'un composant sous forme de caractères littéraux, tels que la légende d'un Button ou le contenu d'un Label. Pour les composants d'entrée comme TextField, utilisez plutôt setValue() pour définir la valeur actuelle du champ.

Button button = new Button();
button.setText("Cliquez Moi");

Label label = new Label();
label.setText("Statut : prêt");

TextField field = new TextField();
field.setValue("Valeur initiale");

Le balisage écrit avec setText() apparaît sous forme de ces caractères et n'est jamais exécuté, ce qui empêche le texte provenant de l'entrée de l'utilisateur ou de données externes d'être interprété comme du balisage actif.

// Affiché comme les caractères littéraux "<b>Status: ready</b>"
component.setText("<b>Status: ready</b>");
Utilisation de la balise <html>

Les versions antérieures de webforJ traitaient une valeur enveloppée dans <html> et passée à setText() comme HTML. Ce comportement est obsolète et sera supprimé dans webforJ 27.00.

La première fois qu'une valeur enveloppée dans <html> atteint setText(), un avertissement est enregistré qui nomme le composant et le site d'appel, afin que l'appel puisse être déplacé vers setHtml().

Pour adopter la valeur par défaut de webforJ 27.00 à l'avance, définissez webforj.legacyHtmlInText sur false. Dans une application Spring, la même valeur est définie via webforj.legacy-html-in-text.

// webforj.legacyHtmlInText = true (par défaut)
component.setText("<html><b>Status: ready</b></html>"); // rend gras

// webforj.legacyHtmlInText = false
component.setText("<html><b>Status: ready</b></html>"); // montre les caractères <b>Status: ready</b>

Rendu de HTML

Certains composants prennent également en charge setHtml() pour les cas où vous devez rendre du balisage HTML en ligne dans le contenu :

Div container = new Div();
container.setHtml("<strong>Texte en gras</strong> et <em>texte en italique</em>");
Script intersites (XSS)

En guise de précaution contre les attaques de script intersites (XSS), n'utilisez setHtml() qu'avec du contenu que vous contrôlez directement.

Attributs HTML

La plupart des configurations dans webforJ se font par le biais de méthodes Java typées plutôt que d'attributs HTML bruts. Cependant, setAttribute() est utile pour passer des attributs d'accessibilité qui n'ont pas d'API dédiée :

Button button = new Button("Soumettre");
button.setAttribute("aria-label", "Soumettre le formulaire");
button.setAttribute("aria-describedby", "form-hint");
Vérifiez le support des composants

Tous les composants ne prennent pas en charge des attributs arbitraires. Cela dépend de l'implémentation sous-jacente du composant.

IDs de composants

Vous pouvez attribuer un ID à l'élément HTML d'un composant en utilisant setAttribute() :

Button submitButton = new Button("Soumettre");
submitButton.setAttribute("id", "submit-btn");

TextField emailField = new TextField("Email");
emailField.setAttribute("id", "email-input");

Les IDs DOM sont couramment utilisés pour les sélecteurs de test et le ciblage CSS dans vos feuilles de style.

Préférez les classes pour le ciblage multi-composants

Contrairement aux classes CSS, les IDs doivent être uniques dans votre application. Si vous devez cibler plusieurs composants, utilisez addClassName() à la place.

IDs gérés par le framework

webforJ assigne également des identifiants automatiques aux composants en interne. L'ID côté serveur (accessible via getComponentId()) est utilisé pour le suivi par le framework, tandis que l'ID côté client (accessible via getClientComponentId()) est utilisé pour la communication client-serveur. Ceux-ci sont séparés de l'attribut id DOM que vous définissez avec setAttribute().

Style

Trois méthodes couvrent la plupart des besoins en matière de style : setStyle() pour les valeurs de propriétés CSS individuelles, et addClassName() et removeClassName() pour appliquer ou supprimer des classes CSS définies dans vos feuilles de style. Utilisez setStyle() pour des ajustements de style mineurs ou ponctuels, et utilisez des classes CSS pour appliquer un style plus large ou réutilisable.

Div container = new Div();
container.setStyle("padding", "20px");

if (isHighPriority) {
container.setStyle("border-left", "4px solid red");
}

Button button = new Button("Basculer");
button.addClassName("primaire", "grande");

if (isLoading) {
button.addClassName("chargement");
}

État du composant

Au-delà du contenu et de l'apparence, les composants ont des propriétés d'état qui déterminent s'ils sont visibles et s'ils répondent à l'interaction de l'utilisateur. Les deux plus souvent utilisés sont setVisible() et setEnabled().

setVisible() contrôle si le composant est rendu dans l'interface utilisateur. setEnabled() contrôle s'il accepte des entrées ou des interactions tout en restant visible. Dans la plupart des cas, désactiver est préférable à cacher : un bouton désactivé communique toujours qu'une action existe mais n'est pas encore disponible, ce qui est moins déroutant que de le faire apparaître et disparaître.

// Révéler un champ supplémentaire lorsqu'une case à cocher est sélectionnée
TextField advancedField = new TextField("Paramètre avancé");
advancedField.setVisible(false);

CheckBox enableAdvanced = new CheckBox("Afficher les paramètres avancés");
enableAdvanced.addValueChangeListener(e -> advancedField.setVisible(e.getValue()));

// Activer un bouton uniquement lorsque le champ requis a une valeur
Button submitButton = new Button("Soumettre");
submitButton.setEnabled(false);

TextField nameField = new TextField("Nom");
nameField.addValueChangeListener(e -> submitButton.setEnabled(!e.getValue().isBlank()));
Désactivé et caché ne sont pas sécurisés

setVisible(false) et setEnabled(false) affectent uniquement l'interface utilisateur. Ils n'empêchent pas un utilisateur déterminé d'invoquer l'action sous-jacente via le navigateur ou une requête falsifiée, donc ne comptez jamais sur eux pour protéger des opérations sensibles. Appliquez toujours le contrôle d'accès côté serveur. Voir Désactivé et caché ne sont pas sécurisés pour plus de détails.

Le formulaire de connexion suivant démontre setEnabled() en pratique. Le bouton de connexion reste désactivé jusqu'à ce que les deux champs aient du contenu, ce qui indique clairement à l'utilisateur que des saisies sont requises avant de continuer :

Afficher le code

Travailler avec des conteneurs

Dans webforJ, la mise en page est gérée par des conteneurs, qui sont des composants pouvant contenir d'autres composants et contrôler leur disposition. Vous ne positionnez pas les composants enfants manuellement ; vous les ajoutez à un conteneur et configurez les propriétés de mise en page de ce conteneur.

Ajout de composants

Tous les conteneurs fournissent une méthode add(). Vous pouvez passer des composants un par un ou tous en même temps :

FlexLayout container = new FlexLayout();

container.add(new Button("Cliquez Moi"));

TextField nameField = new TextField("Nom");
TextField emailField = new TextField("Email");
Button submitButton = new Button("Soumettre");

container.add(nameField, emailField, submitButton);

Options de mise en page

FlexLayout est le conteneur de mise en page principal dans webforJ et couvre la majorité des cas d'utilisation : lignes, colonnes, alignement, espacement et ajustement. Pour des arrangements plus complexes tels que CSS Grid ou un positionnement personnalisé, vous pouvez appliquer du CSS directement via setStyle() ou addClassName() sur n'importe quel composant conteneur. Consultez la documentation sur FlexLayout pour la pleine gamme d'options de mise en page.

Affichage et masquage des sections

Une utilisation courante de setVisible() dans les conteneurs consiste à révéler une interface supplémentaire uniquement lorsque cela est pertinent. Cela garde l'interface centrée et réduit l'encombrement visuel. Plutôt que de naviguer vers une nouvelle vue, vous pouvez afficher une section de la mise en page actuelle en réponse directe à l'entrée de l'utilisateur.

Le panneau de paramètres suivant illustre cela : les préférences de notification de base sont toujours visibles, et une section d'options avancées n'apparaît que lorsque l'utilisateur le demande. Le bouton de sauvegarde s'active dès qu'un paramètre est modifié :

Afficher le code

Gestion des conteneurs

Utilisez remove() et removeAll() pour retirer des composants d'un conteneur à l'exécution :

FlexLayout container = new FlexLayout();
Button tempButton = new Button("Temporaire");

container.add(tempButton);
container.remove(tempButton);

container.removeAll();

Ceci est utile lorsque vous devez remplacer complètement du contenu, comme échanger un indicateur de chargement pour les données chargées.

Validation de formulaire

Coordonner plusieurs composants pour sécuriser une action de soumission est un modèle courant dans les interfaces utilisateur webforJ. L'idée de base est que chaque champ de saisie enregistre un écouteur, et chaque fois qu'une valeur change, le formulaire réévalue si tous les critères sont remplis et met à jour le bouton de soumission en conséquence.

L'exemple ci-dessous configure cela manuellement afin que vous puissiez voir comment l'état des composants et les écouteurs d'événements fonctionnent ensemble. Ce n'est pas l'approche recommandée pour de véritables formulaires : la logique d'écouteurs manuelle devient difficile à maintenir au fur et à mesure que les formulaires grandissent, et elle ne connecte pas vos composants à un modèle de données sous-jacent.

Utilisez la liaison de données pour la validation de formulaire

Pour les formulaires de production, utilisez la liaison de données. Cela couvre la validation, la synchronisation bidirectionnelle entre les composants et votre modèle, et la transformation des valeurs via BindingContext. Le modèle manuel montré ici est uniquement à des fins d'illustration.

Dans ce formulaire de contact, le champ de nom ne doit pas être vide, l'e-mail doit contenir un symbole @, et le message doit comporter au moins 10 caractères :

Afficher le code

Mises à jour de contenu dynamiques

Les composants n'ont pas à rester dans un état fixe après leur création. Vous pouvez mettre à jour le texte, échanger des classes CSS et basculer l'état activé à tout moment en réponse aux événements de l'application. Un exemple courant est de fournir un retour d'information pendant une tâche de longue durée :

Label statusLabel = new Label("Prêt");
Button startButton = new Button("Démarrer le processus");

startButton.onClick(event -> {
startButton.setEnabled(false);
statusLabel.setText("Traitement...");
statusLabel.addClassName("processing");

performTask(() -> {
statusLabel.setText("Terminé");
statusLabel.removeClassName("processing");
statusLabel.addClassName("success");
startButton.setEnabled(true);
});
});

Désactiver le bouton pendant l'exécution de la tâche empêche les soumissions en double, et mettre à jour l'étiquette informe l'utilisateur de ce qui se passe.

ComponentLifecycleObserver

L'interface ComponentLifecycleObserver vous permet d'observer les événements du cycle de vie d'un composant depuis l'extérieur du composant lui-même. Cela est utile lorsque vous devez réagir à la création ou à la destruction d'un composant sans modifier son implémentation. Par exemple, vous pourriez l'utiliser pour maintenir un registre des composants actifs ou libérer des ressources externes lorsqu'un composant est retiré.

Utilisation de base

Appelez addLifecycleObserver() sur n'importe quel composant pour enregistrer un rappel. Le rappel reçoit le composant et l'événement du cycle de vie :

Button button = new Button("Regardez Moi");

button.addLifecycleObserver((component, event) -> {
switch (event) {
case CREATE:
System.out.println("Bouton créé");
break;
case DESTROY:
System.out.println("Bouton détruit");
break;
}
});

Modèle : Registre de ressources

L'événement DESTROY est particulièrement utile pour garder un registre automatiquement synchronisé. Plutôt que de retirer manuellement les composants lorsqu'ils ne sont plus nécessaires, vous laissez le composant notifier le registre lui-même :

public class ResourceRegistry {
private final Map<String, Component> activeComponents = new ConcurrentHashMap<>();

public void track(Component component, String name) {
activeComponents.put(name, component);

component.addLifecycleObserver((comp, event) -> {
if (event == ComponentLifecycleObserver.LifecycleEvent.DESTROY) {
activeComponents.remove(name);
}
});
}
}

Modèle : Coordination des composants

Une classe de coordination qui gère un ensemble de composants liés peut utiliser la même approche pour maintenir sa liste interne précise :

public class FormCoordinator {
private final List<DwcComponent<?>> managedComponents = new ArrayList<>();

public void manage(DwcComponent<?> component) {
managedComponents.add(component);

component.addLifecycleObserver((comp, event) -> {
if (event == ComponentLifecycleObserver.LifecycleEvent.DESTROY) {
managedComponents.remove(comp);
}
});
}

public void disableAll() {
managedComponents.forEach(c -> c.setEnabled(false));
}
}

Quand utiliser

Utilisez ComponentLifecycleObserver pour :

  • Construire des registres de composants
  • Mettre en œuvre la journalisation ou la surveillance
  • Coordonner plusieurs composants
  • Nettoyer des ressources externes

Pour exécuter du code après qu'un composant soit attaché au DOM, consultez whenAttached() dans le guide Composant de composition.

Données utilisateur

Les composants peuvent transporter des données serveur arbitraires via setUserData() et getUserData(). Les deux méthodes prennent une clé pour identifier les données. Cela est utile lorsque vous devez associer des objets de domaine ou un contexte à un composant sans gérer une structure de recherche séparée.

Button button = new Button("Traiter");
button.setUserData("contexte", new ProcessingContext(userId, taskId));

button.onClick(event -> {
ProcessingContext context = (ProcessingContext) button.getUserData("contexte");
processTask(context.getUserId(), context.getTaskId());
});

Puisque les données utilisateur ne sont jamais envoyées au client, vous pouvez stocker en toute sécurité des informations sensibles ou de grands objets sans affecter le trafic réseau.