Aller au contenu principal

Composant ProTable

ProTable est le composant de tableau distant générique de Page Designer. Il permet d'appeler directement une API HTTP et de configurer les colonnes, les outils de recherche, la pagination et les actions de ligne.

Ce guide explique comment :

  • Connecter une Custom URL à une API paginée GET ou POST
  • Transmettre la valeur courante d'un Input ou d'un autre composant via Query Context
  • Lancer une nouvelle recherche depuis la première page avec un bouton Search
  • Conserver les critères actifs pendant la pagination
  • Configurer les chemins de réponse, les colonnes, la clé de ligne et le rendu
  • Implémenter une API compatible avec ProTable à partir de l'exemple Java

Le guide utilise l'exemple de recherche de produits fourni par Spark. L'API contient 23 produits de démonstration et accepte un keyword pour rechercher partiellement, sans tenir compte de la casse, dans le code et le nom du produit.

1. Quand utiliser ProTable​

1.1 Cas d'utilisation recommandés​

Utilisez ProTable lorsque :

  • La page doit appeler directement une API backend spécifique
  • Les données proviennent d'un service tiers ou d'agrégation plutôt que d'un seul Business Object
  • L'API possède sa propre logique de pagination, de filtrage, de tri ou d'autorisation
  • Un bouton appelle une API puis écrit le tableau obtenu avec setTableData

1.2 ProTable, DataList et TaskList​

ComposantDonnées principalesUsage recommandé
ProTableCustom URL ou Model Data SourceAPI HTTP génériques, données agrégées et contrats de pagination spécifiques
DataListBusiness ObjectDQL, champs de modèle, Object Actions et autorisations de données
TaskListSpark TasksFiltres de tâches, statuts, traitement et contexte de tâche

ProTable prend également en charge Model Data Source, dont la liaison au modèle est proche de DataList. Pour les Business Objects, DQL et filtres de modèle, consultez le guide du composant DataList. Ce guide se concentre sur la source Custom URL de ProTable.

2. Exemple utilisé dans ce guide​

API d'exemple :

POST https://spark.hiforce.ai/spark/api/sample/protable/products

La page d'exemple utilise :

  • Source de données : Custom URL
  • Méthode : POST
  • Taille par défaut : 10 enregistrements
  • Left Toolbar : un Input Key Word et un Button Search
  • Query Context : mappe la valeur de l'Input vers le champ keyword
  • Interaction Search : appelle reloadTable sur le ProTable courant
  • Colonnes : code, name, category, price et stock

Après connexion à Spark avec les droits nécessaires, ouvrez la page Runtime de cet exemple pour le vérifier.

3. Contrat de pagination Custom URL​

3.1 Requête POST​

Au chargement de la première page, ProTable fusionne les champs de pagination et les paramètres Query Context dans un corps JSON :

{
"current": 1,
"pageSize": 10,
"keyword": "Graphite"
}
ChampTypeDescription
currentnumberNuméro de page courant, à partir de 1
pageSizenumberNombre d'enregistrements par page
keywordstringParamètre métier ajouté par Query Context dans cet exemple

ProTable gère automatiquement current et pageSize. Ne les redéfinissez pas dans Query Context.

3.2 Requête GET​

Avec GET, les mêmes paramètres deviennent une Query String :

/spark/api/sample/protable/products?current=1&pageSize=10&keyword=Graphite

Les valeurs undefined, null et chaînes vides sont omises. Les tableaux et objets sont sérialisés en chaînes JSON, que le backend doit analyser comme du JSON.

3.3 Structure de réponse par défaut​

L'exemple renvoie le ApiResult standard de Spark, avec les données paginées sous data :

{
"success": true,
"code": 200,
"message": "Les donnees produit ont ete chargees avec succes.",
"data": {
"total": 1,
"current": 1,
"pageSize": 10,
"requestContext": {
"environment": "DEV",
"renderMode": "RUNTIME"
},
"records": [
{
"id": 4,
"code": "DSP-2002",
"name": "Graphite Monitor 32",
"category": "DISPLAY",
"status": "ACTIVE",
"price": 699.00,
"stock": 21,
"updatedAt": "2026-07-25T16:40:00Z"
}
]
}
}

Configurez les chemins ainsi :

Rows Path: data.records
Total Path: data.total
Current Page Path: data.current
Page Size Path: data.pageSize

Les chemins utilisent la notation pointée. Si les lignes se trouvent dans result.items, saisissez result.items dans Rows Path.

Une API paginée doit renvoyer le nombre total d'enregistrements filtrés, et non la taille du tableau de la page courante. Sinon ProTable ne peut pas calculer le nombre de pages.

3.4 En-têtes de contexte des requêtes de page​

Lorsqu'il envoie une requête HTTP réelle via Custom URL, ProTable ajoute automatiquement deux en-têtes standard. Le backend peut les utiliser pour choisir des données de test, limiter l'accès depuis le designer ou enregistrer l'origine de la requête :

En-têteValeursDescription
X-Spark-Page-EnvironmentDEV, TEST, PRODEnvironnement courant de la page ; les aperçus de données dans Page Designer utilisent DEV
X-Spark-Page-Render-ModeDESIGN_PREVIEW, RUNTIMEPage Designer, l'aperçu ouvert depuis le designer et l'aperçu d'enregistrements réels utilisent DESIGN_PREVIEW ; les pages d'exécution normales utilisent RUNTIME

L'environnement et le mode de rendu sont deux dimensions indépendantes. Par exemple, une page d'exécution dans l'environnement de développement envoie DEV + RUNTIME, tandis que le chargement d'enregistrements réels dans Page Designer envoie DEV + DESIGN_PREVIEW. Ces valeurs sont des énumérations stables ; le backend ne doit pas déduire le contexte à partir de l'URL de la page ou du Referer.

Il s'agit du contrat commun à toutes les requêtes backend de Page Designer et Page Runtime, pas seulement à ProTable ou Custom URL. Model Data Source, Data Form, les composants Task, les téléversements, les actions de ligne et Send Request utilisent les mêmes en-têtes. GET et POST se comportent de la même manière. Si une Custom URL cible un service d'une autre origine, sa configuration CORS doit autoriser ces deux en-têtes dans Access-Control-Allow-Headers.

4. Ajouter et configurer ProTable​

4.1 Ajouter le composant​

  1. Ouvrez la page cible dans Page Designer.
  2. Développez Data dans la palette.
  3. Faites glisser ProTable dans un conteneur compatible.
  4. Donnez au composant un nom stable et lisible, par exemple productTable.

Ce nom permet de sélectionner facilement la bonne cible dans une interaction Component API.

4.2 Configurer Custom URL​

Sélectionnez Custom URL dans Data Source, puis saisissez :

PropriétéValeur
URLhttps://spark.hiforce.ai/spark/api/sample/protable/products
Request MethodPOST
Rows Pathdata.records
Total Pathdata.total
Current Page Pathdata.current
Page Size Pathdata.pageSize

Trois formes d'URL sont acceptées :

https://api.example.com/products
connection://erp/products
/products # Sélectionnez également un Connection Key
  • Pour une API Spark de même origine, utilisez une URL complète ou un chemin relatif au site.
  • Pour un service externe, configurez une External Connection dans les paramètres de l'application et utilisez son Connection Key.
  • Conservez secrets, tokens et mots de passe dans la connexion, jamais dans l'URL ou Query Context.
  • L'API reste soumise à l'authentification, aux droits sur les données et à l'autorisation backend. L'ouverture directe d'une API protégée dans le navigateur peut renvoyer 401.

Configurer les Response Fields​

Model Data Source peut lire directement les métadonnées des champs du Business Object. Avec Custom URL, renseignez les Response Fields dans Data Source. Chaque élément contient :

PropriétéDescription
Field PathChemin relatif à un enregistrement, par exemple name ou owner.name
LabelNom affiché dans Columns et les autres sélecteurs de champs
Data TypeTEXT, NUMBER, BOOLEAN, DATE, DATETIME, URL, OBJECT ou ARRAY

Ajoutez les champs manuellement avec le bouton plus, ou cliquez sur Test & Import pour demander jusqu'à 20 enregistrements et fusionner les champs détectés. L'import respecte les règles suivantes :

  • Le backend n'est appelé qu'après un clic explicite ; l'ouverture de la boîte de dialogue n'envoie aucune requête.
  • La requête utilise les valeurs courantes de URL, Method, Query Context et Rows Path.
  • Les objets imbriqués deviennent des chemins pointés ; pour un tableau, seul le champ du tableau est enregistré.
  • Les Label, Data Type et l'ordre existants sont conservés ; seuls les nouveaux chemins sont ajoutés.
  • Les valeurs d'exemple ne sont pas enregistrées, et une réponse vide ou en échec ne remplace jamais les champs existants.

Test & Import utilise le contexte de requête DEV + DESIGN_PREVIEW. Les modifications de Data Source n'entrent dans la configuration de la page qu'après Save ; Cancel abandonne le brouillon courant.

4.3 Configurer Columns​

Ajoutez dans Columns, dans cet ordre :

LabelData Field
Codecode
Namename
Categorycategory
Priceprice
Stockstock

Data Field accepte les chemins pointés. Pour une valeur owner.name, saisissez :

owner.name

Adaptez la largeur au contenu. Une colonne de code peut être étroite, tandis qu'un nom demande plus d'espace. Un texte long ne doit pas déformer tout le tableau.

4.4 Configurer la pagination et la clé de ligne​

Réglages recommandés :

Pagination / Page Size: 10
Row Unique Key: id

Row Unique Key doit être stable et unique. N'utilisez pas un nom, un statut ou une autre valeur susceptible d'être dupliquée ou modifiée.

Dans Runtime, l'utilisateur peut choisir 10, 20 ou 50 lignes par page. Un changement de page ou de taille relance l'API tout en conservant les critères Query Context.

5. Ajouter un critère dans Left Toolbar​

Sélectionnez ProTable et ajoutez un Input dans Left Toolbar :

Label: Key Word
Name: productKeywordInput
Allow Clear: true

L'ID interne de l'Input dans la page d'exemple est field_bfd1e2b2. Ne le recopiez pas. Sélectionnez votre propre Input dans l'éditeur FX.

Avec Allow Clear, l'icône d'effacement apparaît lorsque l'Input contient du texte. Effacer modifie uniquement la valeur ; cliquez ensuite sur Search pour recharger sans mot-clé.

Organisation recommandée :

  • Left Toolbar : Input, Date Picker, Select, Radio et Search
  • Toolbar : Create, Import, Export et autres actions métier

Placez Search dans Left Toolbar pour maintenir le critère et le bouton sur la même ligne, comme dans cet exemple.

6. Lier keyword avec Query Context​

Query Context mappe les valeurs Runtime vers les paramètres HTTP. L'exemple utilise :

Valeur courante de l'Input → variable productKeyword → champ keyword

6.1 Ajouter une variable​

  1. Modifiez Data Source du ProTable.
  2. Cliquez sur FX dans Query Context.
  3. Cliquez sur Add Variable.
  4. Saisissez productKeyword dans Variable Name.
  5. Choisissez Component Value comme Source.
  6. Choisissez l'Input Key Word comme Component.

6.2 Ajouter un paramètre de requête​

Ajoutez ce paramètre :

Parameter: keyword
Value: [[productKeyword]]

Avant chaque requête, Runtime relit la valeur de l'Input. Si elle est vide, keyword est vide ; le backend d'exemple ignore alors ce filtre et renvoie tous les enregistrements.

6.3 Sources de variables courantes​

SourceUsage
Component ValueValeur courante d'un Input, Select, Radio, Date Picker, Uploader ou autre composant
URL ParameterParamètre de l'URL du navigateur
Page ContextContexte de page ou valeur écrite par une interaction précédente
Current RowChamp de l'enregistrement courant dans une action de ligne
Static ValueChaîne, nombre ou booléen fixe

Target Value peut référencer une variable ou combiner des valeurs :

[[productKeyword]]
prefix-[[productKeyword]]

Lorsque Target Value vaut exactement [[variableName]], Runtime conserve si possible le type d'origine. Il n'est pas nécessaire de convertir les tableaux, objets, nombres ou booléens en chaînes.

Ajoutez un Button dans Left Toolbar :

Text: Search
Button Type: Primary

Configurez ensuite son interaction :

  1. Sélectionnez Search et ouvrez Interaction editor.
  2. Ajoutez une action Component API.
  3. Choisissez le ProTable courant, par exemple productTable, dans Target Component.
  4. Choisissez reloadTable dans Function.
  5. Enregistrez l'interaction.

reloadTable démarre une nouvelle recherche :

  1. La page courante revient à 1.
  2. Les valeurs Query Context sont recalculées.
  3. L'API reçoit les nouveaux current, pageSize et keyword.

Cela évite un problème fréquent : si l'utilisateur se trouve en page 2 et recherche un mot-clé qui ne possède qu'un résultat, envoyer current: 2 renverrait correctement un tableau vide. Avec reloadTable, Search envoie current: 1 et affiche le résultat.

La pagination normale n'est pas une nouvelle recherche. Elle change uniquement current et conserve keyword :

Clic sur Search : retour à la page 1 + derniers critères
Clic sur la pagination : nouvelle page + critères conservés

8. Exemple de backend Java​

L'implémentation complète se trouve dans :

spark-sample/src/main/java/hiforce/spark/sample/protable/

spark-console inclut spark-sample, l'API est donc publiée avec Spark Console. Les sections suivantes présentent le code principal attendu par Custom URL.

8.1 DTO de requête​

package hiforce.spark.sample.protable.model;

import lombok.Getter;
import lombok.Setter;

import java.math.BigDecimal;

@Getter
@Setter
public class ProTableProductQueryRequest {

private Integer current = 1;
private Integer pageSize = 10;
private String keyword;
private String category;
private String status;
private BigDecimal minPrice;
private BigDecimal maxPrice;
}

Outre keyword, l'exemple prévoit la catégorie, le statut et l'intervalle de prix. L'implémentation complète comprend aussi conditions et la map sortBy.

8.2 DTO de ligne et résultat paginé​

package hiforce.spark.sample.protable.model;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.List;

@Getter
@AllArgsConstructor
public class ProTableProductDTO {
private final Long id;
private final String code;
private final String name;
private final String category;
private final String status;
private final BigDecimal price;
private final Integer stock;
private final Instant updatedAt;
}

@Getter
@AllArgsConstructor
public class ProTablePageResult<T> {
private final long total;
private final int current;
private final int pageSize;
private final List<T> records;
}

Dans un projet réel, placez ces deux classes public dans deux fichiers portant leur nom. Elles sont regroupées ici uniquement pour présenter le contrat.

8.3 Controller​

package hiforce.spark.sample.protable.web;

import hiforce.spark.base.model.result.ApiResult;
import hiforce.spark.base.web.SparkApiResultHelper;
import hiforce.spark.sample.protable.model.ProTablePageResult;
import hiforce.spark.sample.protable.model.ProTableProductDTO;
import hiforce.spark.sample.protable.model.ProTableProductQueryRequest;
import hiforce.spark.sample.protable.service.ProTableProductService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Locale;

@RestController
@RequestMapping("/spark/api/sample/protable/products")
public class ProTableProductController {

private final ProTableProductService productService;

public ProTableProductController(ProTableProductService productService) {
this.productService = productService;
}

@PostMapping
public ApiResult<ProTablePageResult<ProTableProductDTO>> query(
@RequestBody(required = false) ProTableProductQueryRequest request,
@RequestHeader(value = "Accept-Language", required = false) String language) {
Locale locale = SparkApiResultHelper.resolveLocale(language);
return SparkApiResultHelper.success(
locale,
productService.query(request),
"SPARK-SAMPLE-PROTABLE-0001");
}
}

Le Controller renvoie des DTO et un résultat paginé dans ApiResult. Le message de succès visible est internationalisé avec le Message Code Lattice SPARK-SAMPLE-PROTABLE-0001, et non codé en dur.

8.4 Recherche partielle et pagination​

package hiforce.spark.sample.protable.service;

import hiforce.spark.sample.protable.model.ProTablePageResult;
import hiforce.spark.sample.protable.model.ProTableProductDTO;
import hiforce.spark.sample.protable.model.ProTableProductQueryRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Service
public class ProTableProductService {

private static final int MAX_PAGE_SIZE = 100;

private static final List<ProTableProductDTO> PRODUCTS = List.of(
product(1, "SPK-1001", "SparkBook Air", "COMPUTING", "ACTIVE", "999.00", 32,
"2026-07-27T14:20:00Z"),
product(2, "SPK-1002", "SparkBook Pro", "COMPUTING", "ACTIVE", "1599.00", 18,
"2026-07-28T09:10:00Z"),
product(3, "DSP-2001", "Aurora Monitor 27", "DISPLAY", "ACTIVE", "499.00", 45,
"2026-07-26T08:30:00Z"),
product(4, "DSP-2002", "Graphite Monitor 32", "DISPLAY", "ACTIVE", "699.00", 21,
"2026-07-25T16:40:00Z"),
product(5, "ACC-3001", "Pulse Mechanical Keyboard", "ACCESSORY", "ACTIVE", "129.00", 86,
"2026-07-24T11:00:00Z"),
product(6, "ACC-3002", "Flow Wireless Mouse", "ACCESSORY", "ACTIVE", "79.00", 120,
"2026-07-23T13:15:00Z"),
product(7, "ACC-3003", "Runtime Dock", "ACCESSORY", "ACTIVE", "219.00", 38,
"2026-07-22T09:45:00Z"),
product(8, "STO-4001", "Core SSD 1TB", "STORAGE", "ACTIVE", "149.00", 64,
"2026-07-21T15:20:00Z"),
product(9, "STO-4002", "Core SSD 2TB", "STORAGE", "ACTIVE", "269.00", 41,
"2026-07-20T10:05:00Z"),
product(10, "NET-5001", "Lattice Router", "NETWORK", "ACTIVE", "189.00", 27,
"2026-07-19T17:25:00Z"),
product(11, "NET-5002", "Mesh Access Point", "NETWORK", "ACTIVE", "139.00", 54,
"2026-07-18T12:35:00Z"),
product(12, "CMP-6001", "Build Station", "COMPUTING", "DRAFT", "2399.00", 7,
"2026-07-17T08:50:00Z"),
product(13, "DSP-2003", "Silk Portable Display", "DISPLAY", "ACTIVE", "329.00", 33,
"2026-07-16T14:10:00Z"),
product(14, "ACC-3004", "Spark AI Headset", "ACCESSORY", "ACTIVE", "199.00", 49,
"2026-07-15T10:45:00Z"),
product(15, "ACC-3005", "Console Camera", "ACCESSORY", "ACTIVE", "159.00", 72,
"2026-07-14T09:35:00Z"),
product(16, "STO-4003", "Archive Drive 8TB", "STORAGE", "ACTIVE", "289.00", 25,
"2026-07-13T18:20:00Z"),
product(17, "NET-5003", "Secure Gateway", "NETWORK", "DRAFT", "799.00", 5,
"2026-07-12T07:30:00Z"),
product(18, "CMP-6002", "Runtime Server", "COMPUTING", "ACTIVE", "3499.00", 4,
"2026-07-11T16:00:00Z"),
product(19, "ACC-3006", "USB-C Travel Hub", "ACCESSORY", "DISCONTINUED", "59.00", 0,
"2026-07-10T11:40:00Z"),
product(20, "DSP-2004", "Aurora Display Mini", "DISPLAY", "DRAFT", "279.00", 12,
"2026-07-09T13:05:00Z"),
product(21, "PRN-7001", "Flow Label Printer", "OFFICE", "ACTIVE", "249.00", 28,
"2026-07-08T08:25:00Z"),
product(22, "AUD-8001", "Aurora Conference Speaker", "AUDIO", "ACTIVE", "349.00", 16,
"2026-07-07T15:35:00Z"),
product(23, "PWR-9001", "Core Power Station", "POWER", "DRAFT", "899.00", 9,
"2026-07-06T10:15:00Z"));

public ProTablePageResult<ProTableProductDTO> query(ProTableProductQueryRequest request) {
ProTableProductQueryRequest query = request == null
? new ProTableProductQueryRequest()
: request;

int current = Math.max(query.getCurrent() == null ? 1 : query.getCurrent(), 1);
int pageSize = Math.min(
Math.max(query.getPageSize() == null ? 10 : query.getPageSize(), 1),
MAX_PAGE_SIZE);
String keyword = StringUtils.trimToNull(query.getKeyword());

List<ProTableProductDTO> filtered = PRODUCTS.stream()
.filter(product -> keyword == null
|| StringUtils.containsIgnoreCase(product.getCode(), keyword)
|| StringUtils.containsIgnoreCase(product.getName(), keyword))
.sorted(Comparator.comparing(ProTableProductDTO::getCode))
.toList();

long requestedOffset = (long) (current - 1) * pageSize;
int fromIndex = (int) Math.min(requestedOffset, filtered.size());
int toIndex = Math.min(fromIndex + pageSize, filtered.size());

return new ProTablePageResult<>(
filtered.size(),
current,
pageSize,
new ArrayList<>(filtered.subList(fromIndex, toIndex)));
}

private static ProTableProductDTO product(long id, String code, String name,
String category, String status, String price,
int stock, String updatedAt) {
return new ProTableProductDTO(
id, code, name, category, status,
new BigDecimal(price), stock, Instant.parse(updatedAt));
}
}

Trois comportements sont essentiels :

  1. StringUtils.trimToNull transforme un mot-clé vide en null, donc aucun filtre n'est ajouté.
  2. containsIgnoreCase recherche dans le code et le nom ; Graphite trouve donc Graphite Monitor 32.
  3. Le service filtre et calcule total avant d'extraire la page avec current et pageSize.

Pour garder l'exemple centré sur keyword, le Service ci-dessus omet les filtres de catégorie, statut, prix, conditions génériques et tri multichamp de l'implémentation complète. Les 23 produits et la pagination sont identiques.

8.5 Extension GET​

Pour prendre aussi en charge GET, construisez le même Request DTO à partir des paramètres et réutilisez la méthode POST :

@GetMapping
public ApiResult<ProTablePageResult<ProTableProductDTO>> queryByGet(
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) String keyword,
@RequestHeader(value = "Accept-Language", required = false) String language) {
ProTableProductQueryRequest request = new ProTableProductQueryRequest();
request.setCurrent(current);
request.setPageSize(pageSize);
request.setKeyword(keyword);
return query(request, language);
}

L'API réelle accepte aussi :

ParamètreDescription
categoryÉgalité de catégorie, sans tenir compte de la casse
statusÉgalité de statut, sans tenir compte de la casse
minPrice / maxPriceIntervalle de prix
conditionsTableau de conditions génériques
sortByMap ordonnée des champs vers asc ou desc

Avec GET, conditions et sortBy sont des chaînes JSON encodées dans l'URL. Avec POST, ils sont envoyés directement comme tableau ou objet JSON.

9. Configuration avancée​

9.1 Plusieurs critères​

Ajoutez un Category Select, Status Radio ou Price Input dans Left Toolbar, puis mappez chaque valeur :

{
"keyword": "[[productKeyword]]",
"category": "[[productCategory]]",
"status": "[[productStatus]]",
"minPrice": "[[minimumPrice]]",
"maxPrice": "[[maximumPrice]]"
}

Le backend décide si une valeur vide signifie « ne pas filtrer ». Pour une chaîne optionnelle, utilisez trimToNull ; pour un nombre optionnel, utilisez null plutôt qu'une chaîne spéciale.

9.2 Row Actions​

Ajoutez View, Edit, Delete ou d'autres opérations dans Row Actions. Une action reçoit le contexte de l'enregistrement courant ; FX peut donc lire id, code ou tout autre champ de la ligne.

Après une modification réussie, appelez reloadTable sur le ProTable courant. Ajoutez une confirmation aux actions dangereuses et appliquez les contrôles d'autorisation et métier dans le backend.

9.3 setTableData​

Si un bouton a déjà appelé une API et obtenu un tableau complet, il peut appeler :

setTableData(data)

Cette fonction remplace les données locales et revient à la page 1. Elle ne persiste rien et n'extrait pas automatiquement data.records d'une réponse enveloppée. La valeur doit être le tableau d'enregistrements lui-même.

Pour une pagination distante standard, préférez reloadTable afin que les critères, le total et la pagination restent gérés par le backend.

9.4 Propriétés d'affichage​

PropriétéDescription
Enable Row NumberAffiche dans la première colonne un numéro continu entre les pages
Table SizeDéfinit la densité large, middle ou small
Show HeaderAffiche ou masque l'en-tête de colonnes
BorderedAffiche ou masque les bordures
Row Unique KeyChamp unique de chaque ligne, id par défaut

10. Vérifier l'exemple​

Après enregistrement, vérifiez dans Preview et Runtime :

  1. Sans mot-clé, le premier chargement affiche la page 1 et 23 enregistrements au total.
  2. Passez en page 2 ; les données suivantes s'affichent.
  3. En page 2, saisissez Graphite puis cliquez sur Search.
  4. La requête utilise current: 1 et renvoie uniquement DSP-2002 / Graphite Monitor 32.
  5. Effacez l'Input puis cliquez sur Search ; les 23 enregistrements redeviennent disponibles depuis la page 1.
  6. Recherchez un mot-clé couvrant plusieurs pages, puis paginez ; les requêtes suivantes conservent ce mot-clé.

Dans les outils de développement du navigateur, contrôlez le POST Request Payload :

{
"current": 1,
"pageSize": 10,
"keyword": "Graphite"
}

Vérifiez que data.total, data.current, data.pageSize et data.records correspondent à la requête.

11. Dépannage​

11.1 Graphite est introuvable après une recherche depuis la page 2​

Search exécute peut-être une requête ordinaire au lieu de reloadTable. Vérifiez :

Interaction: Component API
Target Component: ProTable courant
Function: reloadTable

reloadTable revient à la page 1 ; la pagination normale conserve les critères.

11.2 Les données ne changent pas après la saisie​

Vérifiez dans cet ordre :

  1. Query Context contient le paramètre keyword.
  2. productKeyword lit Component Value depuis le bon Input.
  3. Target Value vaut [[productKeyword]].
  4. Le champ du DTO backend s'appelle aussi keyword.
  5. Search appelle reloadTable sur le bon ProTable.

11.3 L'Input n'affiche pas l'icône d'effacement​

Activez Allow Clear et vérifiez que l'Input Runtime contient du texte. L'icône n'apparaît pas pour une valeur vide. Après effacement, cliquez sur Search.

11.4 L'API renvoie des données mais le tableau est vide​

Vérifiez Rows Path. Dans cet exemple :

data.records

Si un chemin personnalisé incorrect est configuré, ProTable ne devine pas un autre chemin et affiche un tableau vide.

11.5 Le total ou la page est incorrect​

Vérifiez que :

  • Total Path pointe vers le total filtré
  • Current Page Path pointe vers la page renvoyée par le serveur
  • Page Size Path pointe vers la taille réellement utilisée
  • La numérotation du backend commence à 1

11.6 L'API renvoie 401, 403 ou une erreur CORS​

  • 401 : la session est invalide ou l'API exige une authentification.
  • 403 : l'utilisateur n'a pas les droits sur l'API ou les données.
  • CORS : le service externe n'autorise pas l'origine Spark courante.

Pour un système externe, préférez External Connection ou un proxy backend contrôlé. N'exposez jamais d'identifiants permanents dans la page.

11.7 Les conditions GET ne sont pas analysées​

GET sérialise objets et tableaux en chaînes JSON. Décodez l'URL et utilisez un parseur JSON côté backend au lieu de découper les objets par virgules. Pour des critères complexes, préférez POST.

11.8 Aucun choix dans Data Field avec Custom URL​

Ouvrez Data Source, configurez les Response Fields, puis enregistrez. Vous pouvez les ajouter manuellement ou utiliser Test & Import. Les Response Fields font partie du contrat de la source de données ; charger un enregistrement dans l'aperçu du tableau ne modifie pas temporairement le catalogue de champs.

12. Liste de contrôle​

  • ProTable possède un nom stable et unique
  • Data Source utilise Custom URL
  • Les Response Fields ont été ajoutés manuellement ou importés avec Test & Import, puis enregistrés
  • URL, Request Method et authentification sont corrects
  • Les chemins Rows, Total, Current Page et Page Size correspondent à la réponse
  • Les Data Fields des colonnes correspondent aux champs des enregistrements
  • Row Unique Key est stable et unique
  • Les paramètres Query Context correspondent aux champs du DTO backend
  • Les variables FX lisent le bon Component Value
  • Search appelle reloadTable sur le ProTable courant
  • Une nouvelle recherche revient à la page 1
  • La pagination normale conserve les critères
  • Les cas mot-clé vide, valide et sans résultat ont été testés
  • Barre d'outils, tableau et pagination ont été vérifiés dans Preview et Runtime

Une fois ces réglages terminés, ProTable fournit une liste stable pour une API HTTP personnalisée et coordonne correctement les contrôles de recherche, la pagination serveur et les interactions de page.