Rendering
Un rendu contrôle la manière dont chaque cellule d'une colonne est affichée. Au lieu d'afficher une valeur brute, un rendu transforme les données de chaque cellule en texte stylé, icônes, badges, liens, boutons d'action ou tout autre visuel qui rend les données plus rapides à lire et plus faciles à manipuler.
Le rendu se fait entièrement dans le navigateur. Le serveur envoie des données brutes et le client gère la présentation, rendant la 'Table' rapide quelle que soit le nombre de lignes.
Assignez un rendu à une colonne en utilisant setRenderer(). Le rendu s'applique uniformément à chaque cellule de cette colonne :
TextRenderer<MusicRecord> renderer = new TextRenderer<>();
renderer.setTheme(Theme.PRIMARY);
table.addColumn("title", MusicRecord::getTitle).setRenderer(renderer);
Si vous n'avez besoin que de transformer ou de formater une valeur de cellule sans produire de structure DOM, utilisez plutôt un fournisseur de valeur. Les rendus créent des éléments DOM supplémentaires pour chaque ligne rendue, ce qui a un coût au moment du rendu. Réservez les rendus pour une sortie visuelle telle que des icônes, des badges, des boutons ou toute présentation basée sur HTML.
webforJ est livré avec des rendus intégrés pour les cas d'utilisation les plus courants. Pour tout ce qui est spécifique à votre application, étendez Renderer et implémentez build() pour retourner une chaîne de modèle lodash qui s'exécute dans le navigateur pour chaque cellule.
Rendus courants
Les exemples suivants parcourent quatre rendus fréquemment utilisés et démontrent le modèle setRenderer() en pratique.
TextRenderer
Affiche le contenu de la cellule en tant que texte brut ou stylé. Appliquez une couleur de thème ou une décoration de texte à une colonne sans changer sa structure, telle que surligner un champ de priorité en rouge ou rendre un identifiant clé en gras.
TextRenderer<MusicRecord> renderer = new TextRenderer<>();
renderer.setTheme(Theme.PRIMARY);
renderer.setDecorations(EnumSet.of(TextDecoration.BOLD));
table.addColumn("title", MusicRecord::getTitle).setRenderer(renderer);
BadgeRenderer
Enveloppe la valeur de la cellule dans un élément de badge. Prend en charge les thèmes, les extensions, la colorisation (couleurs distinctes automatiques par valeur unique), et une icône principale facultative. Utilisez-le pour des valeurs catégorielles telles que des étiquettes, des types ou des étiquettes où des chips visuels distincts aident les utilisateurs à scanner et à comparer rapidement les lignes.
BadgeRenderer<MusicRecord> renderer = new BadgeRenderer<>();
renderer.setTheme(BadgeTheme.PRIMARY);
table.addColumn("musicType", MusicRecord::getMusicType).setRenderer(renderer);
BooleanRenderer
Remplace les valeurs true, false et null par des icônes. Utilisez-le pour toute colonne vrai/faux où une icône communique la valeur plus rapidement que le texte, comme des indicateurs de fonctionnalités, des états actifs/inactifs ou des champs d'opt-in.
// Icônes par défaut
BooleanRenderer<Task> renderer = new BooleanRenderer<>();
table.addColumn("completed", Task::isCompleted).setRenderer(renderer);
// Icônes personnalisées
BooleanRenderer<Task> custom = new BooleanRenderer<>(
TablerIcon.create("thumb-up").setTheme(Theme.SUCCESS),
TablerIcon.create("thumb-down").setTheme(Theme.DANGER)
);
table.addColumn("completed", Task::isCompleted).setRenderer(custom);
CurrencyRenderer
Formate une valeur numérique en montant monétaire en utilisant les règles de la Locale fournie. Utilisez-le pour toute colonne monétaire où le formatage correct en fonction de la locale (symbole, séparateurs, décimales) est important.
// Dollars américains
table.addColumn("cost", MusicRecord::getCost)
.setRenderer(new CurrencyRenderer<>(Locale.US));
// Euros avec la locale allemande
table.addColumn("retail", MusicRecord::getRetail)
.setRenderer(new CurrencyRenderer<>(Locale.GERMANY));
Rendu conditionnel
ConditionalRenderer sélectionne un rendu différent par cellule bas é sur la valeur de la cellule. Les conditions sont évaluées dans l'ordre ; la première correspondance est retenue. Une solution de secours générale peut être définie avec otherwise().
L'exemple suivant montre le rendu conditionnel appliqué à une colonne d'état de facture, alternant entre les variantes BadgeRenderer en fonction de la valeur :
Afficher le code
- InvoiceListView.java
- Invoice.java
- InvoiceService.java
Il fonctionne également bien pour les seuils numériques. Ce tableau de bord serveur utilise ConditionalRenderer pour changer les thèmes ProgressBarRenderer en fonction des niveaux d'utilisation du CPU et de la mémoire :
Afficher le code
- ServerDashboardView.java
- Server.java
- ServerService.java
API Condition
Les conditions sont construites avec des méthodes de fabrique statiques et peuvent être composées avec and(), or(), et negate().
// Égalité de valeur
Condition.equalTo("active")
Condition.equalToIgnoreCase("active")
Condition.in("active", "pending", "new")
// Comparaisons numériques
Condition.greaterThan(100)
Condition.lessThanOrEqual(0)
Condition.between(10, 50)
// Booléen / vacuité
Condition.isTrue()
Condition.isFalse()
Condition.isEmpty()
// Correspondance de chaîne
Condition.contains("error")
Condition.containsIgnoreCase("warn")
// Composition
Condition.greaterThan(0).and(Condition.lessThan(100))
Condition.isEmpty().or(Condition.equalTo("N/A"))
Condition.isTrue().negate()
// Vérification inter-colonnes
Condition.column("status").equalTo("active")
// Expression JavaScript brute
Condition.expression("cell.value % 2 === 0")
Rendu composite
CompositeRenderer combine plusieurs rendus côte à côte dans une seule cellule en utilisant une disposition flex. Utilisez-le pour associer une icône avec un texte, montrer un avatar à côté d'un nom, ou empiler un badge à côté d'un indicateur d'état.
Le répertoire des employés ci-dessous utilise un CompositeRenderer sur la colonne Employé pour afficher un avatar généré automatiquement à côté du nom de chaque employé :
Afficher le code
- EmployeeDirectoryView.java
Rendus personnalisés
Lorsque aucun rendu intégré ne convient à votre cas d'utilisation, étendez Renderer et implémentez build(). La méthode renvoie une chaîne de modèle lodash qui s'exécute dans le navigateur pour chaque cellule de la colonne, exprimée sous forme de mélange de HTML et JavaScript.
Création d'un rendu personnalisé
Étape 1 : Étendez Renderer avec votre type de données de ligne.
public class RatingRenderer extends Renderer<MusicRecord> {
Étape 2 : Surchargez build() et retournez une chaîne de modèle lodash.
@Override
public String build() {
return /* html */"""
<%
const rating = Number(cell.value);
const stars = Math.round(Math.min(Math.max(rating, 0), 5));
const full = '★'.repeat(stars);
const empty = '☆'.repeat(5 - stars);
%>
<span><%= full %><%= empty %></span>
<span style="color: var(--dwc-color-body-text)">(<%= rating.toFixed(1) %>)</span>
""";
}
}
Étape 3 : Assignez le rendu à une colonne.
table.addColumn("rating", MusicRecord::getRating)
.setRenderer(new RatingRenderer());
Pour plus d'informations sur la manière dont la syntaxe Lodash est utilisée pour accéder à des informations de cellule et créer des rendus informatifs, voir cette section de référence.
Accéder à plusieurs colonnes
Utilisez cell.row.getValue("columnId") pour lire les colonnes voisines à l'intérieur du modèle. Cela est utile pour combiner des champs, calculer des deltas ou croiser des données liées.
public class ArtistAvatarRenderer extends Renderer<MusicRecord> {
@Override
public String build() {
return /* html */"""
<%
const name = cell.row.getValue("artist");
const initials = name
? name.split(' ').map(w => w.charAt(0)).join('').substring(0, 2).toUpperCase()
: '?';
%>
<div style="display: flex; align-items: center; gap: 8px;">
<div style="width: 28px; height: 28px; border-radius: 50%;
background: var(--dwc-color-primary); color: white;
display: flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 600;">
<%= initials %>
</div>
<span><%= name %></span>
</div>
""";
}
}
Événements de clic
IconButtonRenderer et ButtonRenderer exposent addClickListener() par défaut. L'événement de clic donne accès à l'objet de données de la ligne via e.getItem().
IconButtonRenderer<MusicRecord> deleteBtn = new IconButtonRenderer<>(
TablerIcon.create("trash").setTheme(Theme.DANGER)
);
deleteBtn.addClickListener(e -> {
MusicRecord record = e.getItem();
repository.delete(record);
table.refresh();
});
table.addColumn("delete", r -> "").setRenderer(deleteBtn);
Performance : rendu paresseux 25.12
Pour les colonnes qui utilisent des rendus visuellement coûteux tels que des badges, des barres de progression, des avatars ou des composants web, activez le rendu paresseux pour améliorer la performance de défilement.
table.addColumn("status", Order::getStatus)
.setRenderer(new BadgeRenderer<>())
.setLazyRender(true);
Lorsque setLazyRender(true) est défini sur une colonne, les cellules affichent un espace réservé animé léger pendant que l'utilisateur défile. Le contenu réel de la cellule se rend une fois le défilement arrêté. Il s'agit d'un paramètre au niveau de la colonne, vous pouvez donc l'activer sélectivement uniquement pour les colonnes qui en bénéficient.
Afficher le code
- LazyRenderView.java
Les rendus de cellules créent plus d'entités dans le DOM, ce qui signifie plus de travail CPU pendant le rendu, quel que soit le rendu qui le crée.
Le rendu paresseux peut aider à réduire l'impact sur les performances si un rendu est réellement nécessaire. Si vous n'avez besoin que de changer ou de formater la valeur, et que vous ne créez pas un DOM complexe, utilisez plutôt un fournisseur de valeur pour transformer la valeur.
Référence des rendus intégrés
webforJ est livré avec un ensemble complet de rendus pour les cas d'utilisation les plus courants. Assignez n'importe lequel d'entre eux à une colonne en utilisant column.setRenderer(renderer).
Afficher le code
- ProductCatalogView.java
- Product.java
- ProductService.java
Texte et étiquettes
TextRenderer - texte stylé avec thème et décorations optionnels
Affiche le contenu de la cellule en tant que texte brut ou stylé. Prend en charge les couleurs de thème et les décorations de texte telles que le gras, l'italique et le soulignement.
TextRenderer renderer = new TextRenderer<>();
renderer.setTheme(Theme.PRIMARY);
renderer.setDecorations(EnumSet.of(TextDecoration.BOLD));
table.addColumn("title", MusicRecord::getTitle).setRenderer(renderer);
BadgeRenderer - valeur affichée à l'intérieur d'un badge
Enveloppe la valeur de la cellule dans un élément de badge. Prend en charge les thèmes, les extensions, la colorisation (couleurs distinctes automatiques par valeur unique), et une icône principale facultative.
BadgeRenderer renderer = new BadgeRenderer<>();
renderer.setTheme(BadgeTheme.PRIMARY);
table.addColumn("musicType", MusicRecord::getMusicType).setRenderer(renderer);
NullRenderer - espace réservé pour les valeurs nulles ou vides
Rend une chaîne de secours configurable lorsque la valeur de la cellule est null ou vide ; sinon, rend la valeur telle quelle.
table.addColumn("notes", MusicRecord::getNotes)
.setRenderer(new NullRenderer<>("N/A"));
Statuts et indicateurs
BooleanRenderer - true/false/null affiché comme icônes
Remplace les valeurs true, false et null par des icônes. Par défaut, cela utilise une coche, une croix et un tiret.
// Icônes par défaut
BooleanRenderer renderer = new BooleanRenderer<>();
table.addColumn("completed", Task::isCompleted).setRenderer(renderer);
// Icônes personnalisées
BooleanRenderer custom = new BooleanRenderer<>(
TablerIcon.create("thumb-up").setTheme(Theme.SUCCESS),
TablerIcon.create("thumb-down").setTheme(Theme.DANGER)
);
StatusDotRenderer - petite dot indicatrice colorée à côté du texte de la cellule
Rend un petit point coloré à gauche de la valeur de la cellule. Mappez les valeurs individuelles aux thèmes, chaînes de couleur CSS, ou instances de java.awt.Color.
StatusDotRenderer renderer = new StatusDotRenderer<>();
renderer.addMapping("Active", Theme.SUCCESS);
renderer.addMapping("Pending", Theme.WARNING);
renderer.addMapping("Cancelled", Theme.DANGER);
table.addColumn("status", Order::getStatus).setRenderer(renderer);
Nombres, monnaie et dates
CurrencyRenderer - formatage de monnaie conscient de la locale
Formate une valeur numérique en montant monétaire en utilisant les règles de la Locale fournie.
// Dollars américains
table.addColumn("cost", MusicRecord::getCost)
.setRenderer(new CurrencyRenderer<>(Locale.US));
// Euros avec la locale allemande
table.addColumn("retail", MusicRecord::getRetail)
.setRenderer(new CurrencyRenderer<>(Locale.GERMANY));
PercentageRenderer - pourcentage avec barre de progression mini optionnelle
Affiche une valeur numérique en tant que pourcentage. Réglez le deuxième argument du constructeur sur false pour empêcher le rendu d'une thin progress bar sous le texte.
PercentageRenderer renderer = new PercentageRenderer<>(Theme.PRIMARY, true);
table.addColumn("completion", Task::getCompletion).setRenderer(renderer);
ProgressBarRenderer - barre de progression pleine pour les valeurs numériques
Rend une barre de progression pleine largeur avec des limites minimum et maximum configurables, un mode indéterminé, et une affichage rayée ou animée. Utilisez setText() avec une expression lodash pour superposer du texte personnalisé sur la barre.
ProgressBarRenderer renderer = new ProgressBarRenderer<>();
renderer.setMax(100);
renderer.setTheme(Theme.SUCCESS);
renderer.setTextVisible(true);
renderer.setText("<%= cell.value %>/100");
table.addColumn("progress", Task::getProgress).setRenderer(renderer);
MaskedTextRenderer - chaîne formatée avec un masque de texte
Applique un masque de caractère à une valeur de chaîne. # correspond à n'importe quel chiffre ; les caractères littéraux sont préservés. Voir règles de masque de texte pour tous les caractères de masque pris en charge.
table.addColumn("ssn", Employee::getSsn)
.setRenderer(new MaskedTextRenderer<>("###-##-####"));
MaskedNumberRenderer - valeur numérique formatée avec un masque numérique
Formate une valeur numérique en utilisant une chaîne de modèle avec des séparateurs conscients de la locale. 0 impose un chiffre ; # est optionnel. Voir règles de masque numérique pour tous les caractères de masque pris en charge.
table.addColumn("price", Product::getPrice)
.setRenderer(new MaskedNumberRenderer<>("###,##0.00", Locale.US));
MaskedDateTimeRenderer - date/heure formatée avec un masque de date
Formate une valeur de date ou d'heure en utilisant des jetons de modèle : %Mz (mois), %Dz (jour), %Yz (année), et d'autres. Voir règles de masque de date pour tous les jetons disponibles.
table.addColumn("released", MusicRecord::getReleaseDate)
.setRenderer(new MaskedDateTimeRenderer<>("%Mz/%Dz/%Yz"));
Liens et médias
EmailRenderer - adresse email sous forme de lien mailto cliquable
Enveloppe la valeur de la cellule dans un lien mailto:. Une icône de mail à thème principal sert d'indication visuelle par défaut.
// Icône de mail par défaut
table.addColumn("email", Contact::getEmail)
.setRenderer(new EmailRenderer<>());
// Icône personnalisée
table.addColumn("email", Contact::getEmail)
.setRenderer(new EmailRenderer<>(TablerIcon.create("at")));
PhoneRenderer - numéro de téléphone sous forme de lien tel cliquable
Enveloppe la valeur de la cellule dans un lien tel:. Sur mobile, toucher ouvre le numéroteur. Une icône de téléphone à thème principal est affichée par défaut.
// Icône de téléphone par défaut
table.addColumn("phone", Contact::getPhone)
.setRenderer(new PhoneRenderer<>());
// Icône personnalisée
table.addColumn("phone", Contact::getPhone)
.setRenderer(new PhoneRenderer<>(TablerIcon.create("device-mobile")));
AnchorRenderer - valeur de cellule en tant que lien hypertexte configurable
Rend un élément d'ancre cliquable. Le href prend en charge les expressions de modèle lodash afin que vous puissiez construire des URL dynamiquement à partir de la valeur de la cellule.
AnchorRenderer renderer = new AnchorRenderer<>();
renderer.setHref("https://www.google.com/search?q=<%= cell.value %>");
renderer.setTarget("_blank");
table.addColumn("title", MusicRecord::getTitle).setRenderer(renderer);
ImageRenderer - image en ligne dans une cellule
Affiche une image. L'attribut src prend en charge les expressions de modèle lodash afin que chaque ligne puisse montrer une image différente.
ImageRenderer renderer = new ImageRenderer<>();
renderer.setSrc("https://placehold.co/40x40?text=<%= cell.value %>");
renderer.setAlt("Couverture");
table.addColumn("cover", MusicRecord::getArtist).setRenderer(renderer);
Personnes et avatars
AvatarRenderer - avatar avec initiales générées automatiquement
Rend un composant avatar. Les initiales sont dérivées automatiquement de la valeur de la cellule. Prend en charge les thèmes et une icône de secours.
AvatarRenderer renderer = new AvatarRenderer<>();
renderer.setTheme(AvatarTheme.PRIMARY);
renderer.setIcon(TablerIcon.create("user"));
table.addColumn("artist", MusicRecord::getArtist).setRenderer(renderer);
Icônes et actions
IconRenderer - icône autonome, cliquable si souhaité
Rend une seule icône. Attachez un écouteur de clic pour un comportement interactif.
IconRenderer renderer = new IconRenderer<>(TablerIcon.create("music"));
table.addColumn("type", MusicRecord::getMusicType).setRenderer(renderer);
IconButtonRenderer - bouton icône cliquable avec accès à la ligne
Rend un bouton d'icône cliquable. L'événement de clic expose l'élément de ligne via e.getItem(), ce qui le rend idéal pour des actions au niveau de la ligne.
IconButtonRenderer renderer = new IconButtonRenderer<>(TablerIcon.create("edit"));
renderer.addClickListener(e -> openEditor(e.getItem()));
table.addColumn("actions", r -> "").setRenderer(renderer);
ButtonRenderer - bouton thématisé dans une cellule
Rend un composant Button complet à l'intérieur de la cellule.
ButtonRenderer renderer = new ButtonRenderer<>("Modifier");
renderer.setTheme(ButtonTheme.PRIMARY);
renderer.addClickListener(e -> openEditor(e.getItem()));
table.addColumn("edit", r -> "Modifier").setRenderer(renderer);
ElementRenderer - élément HTML brut avec contenu lodash
Rend n'importe quel élément HTML avec une chaîne de modèle lodash. C'est la solution de secours pour les situations où aucun rendu intégré ne convient.
ElementRenderer renderer = new ElementRenderer<>("span", "<%= cell.value %>");
table.addColumn("custom", MusicRecord::getTitle).setRenderer(renderer);
Référence de modèle
Les rendus offrent un mécanisme puissant pour personnaliser la manière dont les données sont affichées dans une Table. La classe principale, Renderer, est conçue pour être étendue afin de créer des rendus personnalisés basés sur des modèles lodash, permettant un rendu de contenu dynamique et interactif.
Les modèles lodash permettent l'insertion de HTML directement dans les cellules de la table, les rendant hautement efficaces pour le rendu de données de cellule complexes dans une Table. Cette approche permet la génération dynamique de HTML basée sur les données de cellule, facilitant un contenu riche et interactif dans les cellules de la table.
Syntaxe Lodash
La section suivante décrit les bases de la syntaxe Lodash. Bien qu'il ne s'agisse pas d'une vue d'ensemble exhaustive ou complète, elle peut être utilisée pour commencer à utiliser Lodash dans le composant Table.
Vue d'ensemble de la syntaxe pour les modèles lodash :
<%= ... %>- Interpole les valeurs, insérant le résultat du code JavaScript dans le modèle.<% ... %>- Exécute le code JavaScript, permettant des boucles, des conditionnelles, et plus encore.<%- ... %>- Échappe le contenu HTML, s'assurant que les données interpolées sont à l'abri des attaques d'injection HTML.
Exemples utilisant les données de cellule :
1. Interpolation de valeur simple : afficher directement la valeur de la cellule.
<%= cell.value %>
2. Rendu conditionnel : utiliser la logique JavaScript pour rendre conditionnellement du contenu.
<% if (cell.value > 100) { %> 'Élevé' <% } else { %> 'Normal' <% } %>
3. Combinaison de champs de données : rendre le contenu à l'aide de plusieurs champs de données de la cellule.
<%= cell.row.getValue('firstName') + ' ' + cell.row.getValue('lastName') %>
4. Échappement du contenu HTML : rendre en toute sécurité le contenu généré par l'utilisateur.
Le rendu a accès à des propriétés détaillées des cellules, des lignes et des colonnes sur le côté client :
Propriétés de TableCell :
| Propriété | Type | Description |
|---|---|---|
| column | TableColumn | L'objet colonne associé. |
| first | boolean | Indique si la cellule est la première de la ligne. |
| id | String | L'ID de la cellule. |
| index | int | L'index de la cellule dans sa ligne. |
| last | boolean | Indique si la cellule est la dernière de la ligne. |
| row | TableRow | L'objet ligne associé à la cellule. |
| value | Object | La valeur brute de la cellule, directement de la source de données. |
Propriétés de TableRow :
| Propriété | Type | Description |
|---|---|---|
| cells | TableCell[] | Les cellules de la ligne. |
| data | Object | Les données fournies par l'application pour la ligne. |
| even | boolean | Indique si la ligne est numérotée pair (pour des raisons de style). |
| first | boolean | Indique si la ligne est la première du tableau. |
| id | String | ID unique pour la ligne. |
| index | int | L'index de la ligne. |
| last | boolean | Indique si la ligne est la dernière du tableau. |
| odd | boolean | Indique si la ligne est numérotée impair (pour des raisons de style). |
Propriétés de TableColumn :
| Propriété | Type | Description |
|---|---|---|
| align | ColumnAlignment | L'alignement de la colonne (gauche, centre, droite). |
| id | String | Le champ de l'objet ligne d'où obtenir les données de la cellule. |
| label | String | Le nom à rendre dans l'en-tête de la colonne. |
| pinned | ColumnPinDirection | La direction de fixation de la colonne (gauche, droite, automatique). |
| sortable | boolean | Si vrai, la colonne peut être triée. |
| sort | SortDirection | L'ordre de tri de la colonne. |
| type | ColumnType | Le type de la colonne (texte, nombre, booléen, etc.). |
| minWidth | number | La largeur minimale de la colonne en pixels. |