La listbox

Les propriétés du bloc lui-même sont décrites sur la page Listbox. Cette page couvre ce que le schéma ne peut pas exprimer : la collection de colonnes, et les comportements qui échouent en silence.

D'où viennent les lignes

PropriétéRôle
vt_TableNameObligatoire. Sans elle, la listbox s'affiche vide, sans erreur
vt_FirstRequestL'ensemble de départ

vt_FirstRequest attend une relation ou une collection, pas une chaîne de requête : Entity.MyLines fonctionne, un query(...) écrit à la main non. Et ne la construisez jamais avec un ternaire qui renvoie deux types différents : c'est le bloc entier qui échoue.

Pour une listbox alimentée par une collection écrite en dur plutôt que par une table, c'est cette même propriété qui porte la collection.

Les colonnes ne sont pas dans le schéma

vc_FieldDisplay est une collection d'objets colonne, rendue de façon asynchrone par columnProperties.html, et volontairement absente du schéma du bloc : sa forme dépend de la table et de vt_FirstRequest. Un objet colonne porte son libellé, son format, son alignement, ses couleurs, ses conditions, ses largeurs, sa visibilité par point de rupture, et ses propres événements.

Piège : n'écrasez jamais vc_FieldDisplay en bloc. Une mise à jour remplace la valeur : lisez la collection actuelle, modifiez-la, et renvoyez-la complète. La reconstruire de mémoire, c'est perdre en silence le style des colonnes.

Points de rupture : absent veut dire visible

Chaque colonne peut déclarer vb_DisplayField par point de rupture (default, sm, md, lg, xl), plus vl_Order pour réordonner les colonnes selon la taille d'écran.

Quand la clé est absente, la colonne est visible : le gabarit listboxRow.html vaut True par défaut.

À savoir : la documentation V20 affirme l'inverse comme un piège critique (« sans configuration des points de rupture, les cellules de la listbox sont invisibles », null traité comme faux pour les cellules mais vrai pour les en-têtes). Ce n'est plus vrai dans le composant V21 : un seul calcul sert aux deux, et il vaut visible par défaut.

Au point de rupture small, la listbox replie toutes les colonnes : c'est le comportement voulu, en forme de cartes, pas un défaut de mise en page.

Le tri

La clé qui rend une colonne triable est vt_sortable, pas vt_SortFieldName.

Pour un attribut calculé, le tri demande une Function orderBy sur l'attribut, sinon 4D n'a rien sur quoi trier. Même chose pour la recherche : un attribut calculé interrogé sans Function query déclenche un parcours séquentiel.

La recherche

Une listbox a une zone de recherche native. Ne construisez pas de blocs fieldText séparés pour la filtrer : branchez plutôt la zone native.

  • Un conteneur de recherche pilote une seule listbox.
  • La recherche porte sur le vrai champ, pas sur un nom de colonne personnalisé.
  • @ est un joker dans une valeur recherchée : une recherche sur un e-mail correspond donc de façon large, sauf si la comparaison est exacte.

Les événements

Au niveau du bloc : onSelect, onSelectRows, onDoubleClick.

Une action par ligne est un événement de COLONNE, pas un événement de bloc : posez onClick sur la colonne et lisez This.uuidKey. Une cellule éditable est aussi un événement de colonne (popupSelect, popupInput*), et une clé vide est ignorée.

Une fonction appelée derrière popupInput* doit renvoyer vo_Line pour que le client rafraîchisse la cellule sans recharger toute la listbox.

Ce qui ressemble à des bugs

  • Le rendu est asynchrone (quelques secondes). Un test qui lit le DOM immédiatement ne trouve rien : attendez les lignes avant de conclure.
  • Une listbox dans un onglet masqué est vide au premier affichage et remplie au second : BWEB saute les listbox des volets masqués. Appelez loadAllListboxesIfNotLoaded(pane) à l'activation de l'onglet.
  • reloadListbox est une fonction côté client ; l'action côté serveur est displayListbox. Appeler la mauvaise depuis le mauvais côté ne fait rien.
  • « Tout sélectionner » porte sur toute la sélection, pas sur la page visible.
  • Un <a href> dans une cellule ouvre le panneau de détail et navigue.

Liste de contrôle pour en créer une par l'API

Une listbox mal configurée ne produit aucune erreur : le bloc apparaît, les en-têtes de colonnes apparaissent, et le corps reste sur « aucun résultat ». Rien côté client, rien côté serveur, rien dans le débogueur. Vérifiez donc point par point au lieu d'attendre un message.

  1. vt_TableName présent dès que la source est une table 4D
  2. chaque propriété vl_* est un entier (20), jamais un texte ("20") : vl_LengthByPage, vl_DisplayLine, vl_MinDisplayLine
  3. vt_DisplayListboxType renseigné (fill est la réponse habituelle)
  4. vt_FirstRequest encodé en base64
  5. vt_FirstRequest passe par une relation et renvoie un seul type : pas de ternaire qui mélange une entity selection et une collection
  6. events.onDisplayListboxRows présent : sans lui, aucune donnée n'est jamais chargée
  7. chaque colonne de vc_FieldDisplay porte ses points de rupture
  8. le vt_howgetpk de chaque colonne vaut Entity (table) ou Collection (données en dur)
  9. vt_ConditionColor / vt_ConditionBackColor déclarés, même vides
  10. avant d'appliquer Year of / Day of dans un vt_FieldFormula, vérifiez le vrai type du champ dans catalog.4DCatalog : un champ nommé startDate peut très bien être stocké en texte ISO

Si elle reste vide, comparez-la propriété par propriété avec une listbox qui fonctionne sur la même page. La différence saute aux yeux en quelques secondes ; lire le moteur de rendu coûte une heure.

À savoir : en V21, ces propriétés sont rangées dans properties. Les notes écrites pour la V20 les placent dans htmlProperties / blockProperties, qui n'existent plus.

Voir aussi