Aller au contenu principal

Afficher une liste page par page

Objectif​

Afficher une table vingt lignes à la fois, permettre à quelqu’un d’y chercher, et placer en dessous des boutons Précédent et Suivant qui savent quand s’arrêter.

Pourquoi cela existe​

Une liste dessinée charge ce que vous lui demandez. Demandez tout, et une table de neuf cents lignes arrive en une seule réponse et défile à n’en plus finir ; demandez-en vingt, et rien à l’écran ne peut dire si ces vingt sont les vingt dernières ou les premières de neuf cents.

La requête s’est donc enrichie de deux choses : une page (skip) et un endroit où placer le comptage (countInto).

Une seule requête fait tout​

loadRecords("par_case", "cases", {
top: num(getState("pageSize")),
skip: getState("page") * num(getState("pageSize")),
contains: { par_name: getState("query") },
orderBy: "par_name",
countInto: "caseTotal"
});

num(…) est là parce que la taille de page provient d’une liste déroulante, et que tout contrôle proposant un choix renvoie les mots plutôt que le nombre — voir La taille de page plus bas.

ÉlémentContenu
tople nombre de lignes que contient cette page
skiple nombre de lignes à sauter d’abord — des lignes, pas des pages
wheredes paires champ/valeur qui doivent toutes correspondre exactement
containsdes paires champ/sous-chaîne — ce dont a besoin une zone de recherche
orderBy / descendingl’ordre
countIntoun champ d’état recevant le nombre total de lignes correspondantes, sans tenir compte de la page

skip compte des lignes plutôt qu’un numéro de page, parce que top compte déjà des lignes. Un écran qui contiendrait les deux devrait les garder cohérents, et la façon dont cela tourne mal est silencieuse : quelqu’un change la taille de page, oublie de réinitialiser la page, et atterrit sur la page 7 d’une liste qui n’en a plus que 3.

Une valeur contains vide ne compte pour rien : vous pouvez donc transmettre directement votre zone de recherche. Une zone où personne n’a tapé signifie tout, pas les lignes contenant la chaîne vide.

countInto est gratuit. La requête de la plateforme compte de toute façon : demander le total ne coûte donc pas de seconde requête. Un écran sans bouton Suivant l’omet et ne paie rien.

Étapes​

  1. Déclarez l’état dont la liste a besoin : cases ([]), caseTotal (0), page (0), pageSize ("20" — la valeur propre de la liste déroulante, donc des mots), query ("").

  2. Placez la requête ci-dessus dans le gestionnaire Chargé de l’écran.

  3. Dessinez Précédent et Suivant, et liez leur propriété Activé :

    • Précédent — state.page > 0
    • Suivant — (state.page + 1) * num(state.pageSize) < state.caseTotal
  4. Leurs gestionnaires changent de page et relancent la requête :

    setState("page", getState("page") + 1);
    loadRecords( … the same query … );
  5. Dessinez la légende. Un nombre ne peut pas être ajouté directement à une phrase — BS Lang refuse de mélanger une chaîne et un nombre et indique Only number or string — alors enveloppez-le :

    "Showing " + text(state.cases.length()) + " of " + text(state.caseTotal)
  6. Dessinez la zone de recherche comme une zone de texte liée à state.query, et donnez-lui un gestionnaire change qui revient à la page zéro et relance la requête. Une zone de texte valide sa saisie quand on la quitte ou quand on appuie sur Entrée : cela fait donc une requête par recherche plutôt qu’une par lettre.

La taille de page​

Une liste déroulante, à l’extrémité droite de la rangée, proposant 10, 20, 30, 40, 50, 100 et 200 :

  • Dessinez une boîte, faites-en un contrôle Liste déroulante, et saisissez les tailles dans sa liste d’options.
  • Liez sa Valeur à state.pageSize — un simple chemin d’état, pour que le choix de quelqu’un soit réécrit avant toute autre chose.
  • Donnez-lui un gestionnaire change qui ramène la page à zéro et relance la requête.
  • Placez les mots Taille de page à l’intérieur de la boîte plutôt qu’à côté. Ce que vous dessinez à l’intérieur d’un contrôle devient son indication et le nom qu’annonce un lecteur d’écran ; une légende devant lui répéterait ce que la liste déroulante fermée dit déjà.

Elle renvoie les mots, pas le nombre. Tout contrôle proposant un choix le fait — state.pageSize contient donc "20", et l’utiliser dans un calcul demande num(…) :

num(state.pageSize) * state.page

Sans cela, BS Lang refuse la paire et indique Only number or string, la même règle qui fait qu’une légende a besoin de text(…) — ce sont les deux sens d’une même conversion. num(…) renvoie 0 pour tout ce qui n’est pas un nombre : un sélecteur auquel on n’a pas touché ne peut donc pas casser l’écran.

Revenez toujours à la page zéro quand la forme de la liste change — une nouvelle taille de page, une nouvelle recherche. Une liste filtrée restée à la page sept n’affiche rien, et donne l’impression d’une recherche cassée.

Chercher dans un sélecteur​

C’est ce même contains qui rend une recherche utilisable. Dans l’exemple Support desk, la carte du sélecteur de contact a sa propre zone de texte, dont le gestionnaire change relance

loadRecords("contact", "contacts", { top: 8, orderBy: "fullname",
contains: { fullname: getState("contactQuery") } });

C’est la réponse de l’environnement, pas un filtre sur les huit lignes déjà présentes dans la carte — toute la différence entre un sélecteur et un sélecteur qui ne trouve que ce qu’il a déjà récupéré.

Ce qui n’existe pas ici​

Il n’y a pas de ou. contains accepte plusieurs champs et les combine par ET, ce qui ne correspond pas à ce que signifie une zone de recherche portant sur trois colonnes. Chercher dans l’un quelconque de plusieurs champs, c’est là qu’un filtre cesse d’être une ligne dans un gestionnaire et devient le concepteur de requêtes dont la plateforme dispose déjà.

Dépannage​

  • La légende affiche Only number or string. — un nombre est ajouté à une phrase. Enveloppez-le dans text(…). Le même message sur une somme est le problème inverse : les mots d’un contrôle sont utilisés comme un nombre, enveloppez-les donc dans num(…).
  • La taille de page ne fait rien, ou la liste se vide quand elle change. — state.pageSize contient les mots de la liste déroulante. top et skip ont besoin de num(…) autour.
  • Suivant ne se désactive jamais. — rien n’écrit le total. Ajoutez countInto à la requête.
  • La recherche ne trouve rien après la première page. — le gestionnaire de recherche ne réinitialise pas page.
  • La liste relance la requête à chaque frappe. — le gestionnaire est placé sur quelque chose qui se déclenche à chaque caractère. Placez-le sur le change de la zone, qui se déclenche quand on la quitte.

Scénarios associés​