Composant visuel intermediaire qui affiche des filtres interactifs (facettes) bases sur les valeurs categoriques des données.

Visuel et intermediaire : Ce composant affiche des controles de filtre ET redistribue les données filtrees aux composants en aval via le systeme d'événements.

Position dans le pipeline

dsfr-data-source → dsfr-data-normalize → dsfr-data-facets → dsfr-data-chart / dsfr-data-list

Normaliser avant dsfr-data-facets permet d'avoir des valeurs propres et coherentes dans les filtres (pas de doublons dus aux espaces ou casses differentes).

Cas d'usage

Attributs

AttributTypeDéfautDescription
idString-Requis. Identifiant de la sortie (données filtrees).
sourceString""ID de la source de données a ecouter
fieldsString""Champs à exposer comme facettes (virgule-séparés). Vide = auto-détection sur les données chargées ; en server-facets, vide = découverte des facettes déclarées par le jeu de données, pour les adaptateurs qui savent les découvrir (#680 — métadonnées du jeu, colonnes à choix ; détail par fournisseur dans la table des capacités d'ARCHITECTURE)
labelsString""Labels custom : "field:Label | field2:Label 2"
value-labelsString""Libellé des VALEURS d'une facette (#928) — labels nomme les CHAMPS, celui-ci nomme ce qu'ils contiennent. Une facette posée sur un champ de code affiche « Finistère » et continue de filtrer « 29 » : la valeur diffusée au contexte, à l'URL et au where reste le CODE. Deux grammaires, distinguées par la première lettre : - champ compagnon, entrées séparées par | comme labels et display : value-labels="dep_code:dep_nom | code_fede_ref:federation". Le libellé est lu dans les MÊMES lignes que la valeur ; il doit donc figurer dans les données reçues (au besoin, l'ajouter au select) ; - table figée en JSON, quand aucun champ compagnon n'existe : value-labels='{"dep_code":{"29":"Finistère","56":"Morbihan"}}'. Une valeur absente de la table reste affichée telle quelle. Le tri alpha et la recherche portent alors sur le libellé. En server-facets, la réponse de l'API facettes ne porte que des valeurs : les libellés sont lus dans les lignes chargées par la source, donc connus pour les valeurs présentes dans ces lignes ; une valeur de facette absente de la page courante reste affichée par son code. Sur un champ de code, poser une table figée lève ce doute.
defaultString""Valeur pré-sélectionnée par champ, même grammaire que labels : default="region:Toutes régions | secteur:Tous secteurs" (#932). Sans sélection, une facette n'émet aucun filtre — ce qui est juste quand l'absence de filtre veut dire « tout ». Ça ne l'est plus quand l'agrégat national est une LIGNE du jeu (« Toutes régions ») à côté d'une ligne par région : le total porte alors sur le cumul, sans avertissement. Un champ nommé ici porte donc TOUJOURS une valeur. Ordre de résolution : une valeur lue dans l'URL (url-params, ou l'URL du contexte en mode context) l'emporte ; le défaut ne s'applique qu'à un champ sans sélection. Conséquences sur un champ à défaut : la remise à zéro (bouton, tag retiré, dernière case décochée) revient au défaut et non à l'absence de filtre, et les options « Tous » de select et radio-inline ne sont plus rendues — elles ne pourraient que revenir au défaut. Une valeur par défaut absente des données est rendue cochée et « (indisponible) », comme toute sélection orpheline (#310).
max-valuesNumber6Nb de valeurs visibles par facette avant "Voir plus"
disjunctiveString""Champs en mode multi-sélection OU (virgule-séparés)
sortStringcountTri des valeurs de chaque facette, grammaire critere:sens alignée sur order-by de dsfr-data-query (#645) : - count:desc (défaut) : du plus fréquent au plus rare - count:asc : du plus rare au plus fréquent - alpha:asc : A -> Z (collation française) - alpha:desc : Z -> A Raccourcis : count = count:desc, alpha = alpha:asc. Formes -count / -alpha DÉPRÉCIÉES : conservées à l'identique (-count = rare d'abord, -alpha = Z -> A) mais un avertissement console invite a passer a la forme explicite ; retrait dans une version majeure. Tri PAR CHAMP (#741), même grammaire à barre verticale que labels, display et cols : champ:critere[:sens], par exemple sort="annee:alpha:asc | categorie:count:desc". Une facette d'années se range alphabétiquement pendant qu'une facette de catégories reste rangée par fréquence, sans dupliquer le composant. Un champ non nommé garde le tri par défaut ; l'entrée *:critere[:sens] change ce défaut (sort="*:alpha | annee:count:desc").
searchableString""Champs avec barre de recherche (virgule-séparés)
hide-emptyBooleanfalseMasquer les facettes avec une seule valeur
displayString""Mode d'affichage par facette : "champ:mode | champ2:mode". Défaut = checkbox. - checkbox : cases à cocher visibles dans un fieldset DSFR (sélection multiple) - select : liste déroulante native fr-select (sélection unique) - multiselect : menu déroulant repliable avec cases à cocher et recherche (sélection multiple) - radio : menu déroulant repliable contenant des boutons radio et une recherche (sélection unique) — sera renommé radio-dropdown dans une version majeure - radio-inline : boutons radio DSFR visibles en ligne, précédés d'une option « Tous » qui retire la sélection (sélection unique, #684)
hide-countsBooleanfalseMasquer les compteurs a cote de chaque valeur de facette
spanString""Largeur des facettes sur la grille de 12 colonnes, à partir de 768 px : "6" pour toutes, ou "annee:3 | categorie:6" par facette. Remplace cols, même sens et même grammaire, sans l'ambiguïté du mot : sur dsfr-data-display et dsfr-data-kpi-group, cols compte des éléments par ligne (#790). Prime sur cols s'ils sont posés ensemble.
per-rowString""Nombre de facettes par ligne à partir de 768 px (en dessous : une par ligne) — 1, 2, 3, 4, 6 ou 12. Se combine avec span par facette : une facette nommée dans span garde sa largeur, les autres se partagent la ligne selon per-row (#790).
colsString""Colonnage DSFR des facettes : "6" (global) ou "field:4 | field2:6" (par facette), en colonnes de la grille de 12 — une LARGEUR, pas un nombre de facettes par ligne. Appliqué à partir de 768 px ; en dessous, chaque facette occupe toute la ligne (fr-col-12 fr-col-md-N, #788). Sans cols, grille automatique qui se replie seule.
server-facetsBooleanfalseActive le mode facettes serveur : les valeurs et leurs compteurs sont demandés à l'API au lieu d'être calculés sur les lignes chargées. Requiert une source amont dont l'adaptateur déclare la capacité serverFacets (table des capacités d'ARCHITECTURE) ; sinon, repli sur les facettes calculées localement. Sans fields, un appel de découverte au premier cycle liste les facettes déclarées par le jeu, pour les adaptateurs qui savent les découvrir (mémorisé, invalidé si la source ou dataset-id change, #680). Les facettes de type date (valeurs par année) sont filtrées par intervalle et non par égalité (#676).
static-valuesString""Valeurs de facettes pre-calculees (JSON). Format: {"field": ["val1", "val2"], "field2": ["a", "b"]} Quand cet attribut est défini, les facettes utilisent ces valeurs sans les calculer depuis les données. Les selections envoient des commandes WHERE dans le dialecte de l'adaptateur amont (colon à défaut) au dsfr-data-query en amont. Attribut fields requis (pas d'auto-detection).
url-paramsBooleanfalseActive la lecture des paramètres d'URL comme pré-sélections de facettes. Sans url-param-map, seuls les paramètres qui portent le nom d'une facette EFFECTIVE sont lus (champs de fields, ou facettes détectées) — jamais n'importe quelle colonne des données (#773). Dès qu'un dsfr-data-context est présent, préférer context="id" : le contexte porte alors l'URL, un paramètre par champ, et url-params est ignoré. Un paramètre lu à la fois par une facette autonome et par un contexte à url-sync est une erreur de configuration.
url-param-mapString""Mapping URL param -> champ facette : "param:field | param2:field2". Si vide, correspondance directe
url-syncBooleanfalseSynchronise l'URL quand l'utilisateur change les facettes (replaceState — pas d'entrée d'historique par clic)
contextString""Id du dsfr-data-context auquel s'enregistrer (#678, ADR-104). La facette devient alors un filtre du contexte, un par champ : c'est le contexte qui diffuse a ses sources cibles et qui porte l'URL (url-sync et url-params de la facette sont ignorés — reporter url-param-map sur le contexte). Le contexte peut être déclaré après la facette dans la page. Vide = comportement autonome historique (commande directe à source). Le contexte délègue chaque sélection aux sources qu'il vise : le champ doit donc exister SUR CES SOURCES. Une facette sur une colonne calculée en aval (compute d'un normalize) ne peut pas passer par le contexte — c'est une erreur de configuration nommée quand le contexte le sait (#805), un HTTP 400 de l'API sinon ; la garder autonome, chaînée en aval, avec un url-param-map qui borne sa lecture d'URL (#773).
no-resetBooleanfalseMasque le bouton local « Réinitialiser les filtres » (#679, #640 pt 9). À poser quand un dsfr-data-context-tags clear-all fait office de « tout effacer » pour la page (mode context), ou pour qu'une colonne de facettes ne change pas de hauteur à la première sélection.

Événements : le composant n'émet pas d'événement custom propre ; il participe au data-bridge — ré-émission des données filtrées sous son id (dsfr-data-loaded / -loading / -error) en mode client, et commandes { where, whereKey } vers la source en mode serveur/statique.

Compter autre chose que des lignes : weight-field

Le compteur d'une facette annonce par défaut un nombre de lignes. Sur une table de mesures, « 1 240 » relevés ne dit rien au lecteur : ce qu'il veut savoir, c'est combien d'élèves, d'agents ou d'euros se trouvent derrière la modalité. weight-field nomme un champ numérique dont la somme remplace le nombre de lignes dans les compteurs (#739). Le tri sort="count" porte alors sur cette somme.

<dsfr-data-facets
  source="src"
  fields="academie, niveau"
  weight-field="effectif">
</dsfr-data-facets>

Une valeur non numérique compte pour zéro ; si le champ est absent de toutes les lignes, un avertissement console le signale. Côté client uniquement, et c'est assumé : en mode server-facets, la réponse de l'API facettes ne porte qu'un nombre de lignes, jamais la somme d'une mesure. Plutôt que d'afficher un nombre de lignes sous un libellé de somme, les compteurs y sont masqués, une erreur de configuration est posée (console et data-dsfr-config-error) et un avertissement DSFR est rendu au-dessus des facettes. Même chose en static-values, où les compteurs sont déjà masqués faute de données.

Logique de filtrage : au sein d'une facette, les selections sont en OU (afficher Paris ou Lyon). Entre facettes differentes, c'est du ET (region = PACA ET type = Commune). Les compteurs se recalculent dynamiquement.

Modes d'affichage :
checkbox (défaut) : checkboxes DSFR dans un fieldset ouvert.
select : liste deroulante DSFR native, selection exclusive.
multiselect : dropdown DSFR avec checkboxes, recherche, "Tout sélectionner/deselectionner".
radio : dropdown DSFR avec radio buttons, recherche, selection exclusive.
Le mode select/radio est automatiquement exclusif, multiselect automatiquement disjonctif.

Facettes server-side : Avec une source api-type="opendatasoft" et l'attribut server-side, les valeurs des facettes et les compteurs sont calcules directement par l'API (pas de téléchargement complet des données). Les exemples ci-dessous utilisent le dataset Prix du controle technique (~133 000 enregistrements) de data.economie.gouv.fr.

Exemple 1 : tableau filtrable avec facettes server-side

Les facettes Region (multiselect), Type de vehicule (select) et Energie (radio) filtrent le tableau des prix du controle technique avec colonnage DSFR (cols="4").

Code

<dsfr-data-source id="src"
  api-type="opendatasoft"
  base-url="https://data.economie.gouv.fr"
  dataset-id="prix-controle-technique"
  server-side
  page-size="10">
</dsfr-data-source>

<dsfr-data-facets id="filtered" source="src"
  server-facets
  fields="nom_region, cat_vehicule_libelle, cat_energie_libelle"
  labels="nom_region:Region | cat_vehicule_libelle:Type de vehicule | cat_energie_libelle:Energie"
  display="nom_region:multiselect | cat_vehicule_libelle:select | cat_energie_libelle:radio"
  cols="4">
</dsfr-data-facets>

<dsfr-data-list source="filtered"
  columns="cct_commune, nom_departement, cat_vehicule_libelle, cat_energie_libelle, prix_visite"
  server-sort
  pagination="10">
</dsfr-data-list>

Exemple 2 : graphique filtre par region

La facette Region en mode multiselect filtre les données, puis dsfr-data-query agrège le prix moyen du controle technique par departement pour le graphique en barres.

Code

<dsfr-data-source id="src" api-type="opendatasoft"
  base-url="https://data.economie.gouv.fr"
  dataset-id="prix-controle-technique">
</dsfr-data-source>

<dsfr-data-facets id="filtered" source="src"
  server-facets
  fields="nom_region"
  labels="nom_region:Region"
  display="nom_region:multiselect"
  sort="alpha">
</dsfr-data-facets>

<dsfr-data-query id="stats" source="filtered"
  group-by="nom_departement"
  aggregate="prix_visite:avg:Prix_moyen"
  order-by="Prix_moyen:desc"
  limit="15">
</dsfr-data-query>

<dsfr-data-chart source="stats" type="bar"
  label-field="nom_departement"
  value-field="Prix_moyen"
  selected-palette="categorical">
</dsfr-data-chart>

Exemple 3 : KPI + carte filtres par region

Un même dsfr-data-facets alimente a la fois des KPI et une carte. Sélectionner des regions met a jour simultanement les indicateurs et la carte departementale.

Code

<dsfr-data-source id="src" api-type="opendatasoft"
  base-url="https://data.economie.gouv.fr"
  dataset-id="prix-controle-technique">
</dsfr-data-source>

<dsfr-data-facets id="filtered" source="src"
  server-facets
  fields="nom_region"
  labels="nom_region:Region"
  display="nom_region:multiselect"
  sort="alpha">
</dsfr-data-facets>

<!-- KPI sur les données filtrees -->
<dsfr-data-kpi source="filtered" value="count" label="Centres" format="nombre"></dsfr-data-kpi>
<dsfr-data-kpi source="filtered" value="prix_visite:avg" label="Prix moyen" format="euro"></dsfr-data-kpi>

<!-- Carte sur les données filtrees et agregees -->
<dsfr-data-query id="stats" source="filtered"
  group-by="code_departement"
  aggregate="prix_visite:avg:prix_moyen">
</dsfr-data-query>

<dsfr-data-chart source="stats" type="map"
  code-field="code_departement"
  value-field="prix_moyen"
  selected-palette="sequentialAscending">
</dsfr-data-chart>

Exemple 4 : les 4 modes d'affichage

Quatre facettes avec des modes differents : radio pour l'Energie (dropdown avec radio buttons, selection exclusive), multiselect pour la Region (dropdown avec checkboxes, recherche et "Tout sélectionner"), select pour le Type de vehicule (liste deroulante native DSFR), et checkbox (défaut) pour le Departement.

Code

<dsfr-data-facets id="filtered" source="src"
  server-facets
  fields="cat_energie_libelle, nom_region, cat_vehicule_libelle, nom_departement"
  labels="cat_energie_libelle:Energie | nom_region:Region | cat_vehicule_libelle:Type | nom_departement:Departement"
  display="cat_energie_libelle:radio | nom_region:multiselect | cat_vehicule_libelle:select"
  max-values="6">
</dsfr-data-facets>

<dsfr-data-list source="filtered"
  columns="cct_commune, nom_departement, cat_vehicule_libelle, prix_visite"
  pagination="5">
</dsfr-data-list>

Exemple 5 : masquer les compteurs

L'attribut hide-counts masque les compteurs a cote de chaque valeur de facette, pour un affichage plus epure.

Code

<dsfr-data-facets id="filtered" source="src"
  server-facets
  fields="nom_region, cat_vehicule_libelle"
  labels="nom_region:Region | cat_vehicule_libelle:Type de vehicule"
  display="nom_region:multiselect | cat_vehicule_libelle:select"
  hide-counts
  cols="6">
</dsfr-data-facets>

Exemple 6 : colonnage DSFR des facettes

L'attribut cols permet de controler la largeur de chaque facette dans la grille DSFR. Ici, Region occupe la moitie (col-6), Type de vehicule un tiers (col-4) et Energie toute la largeur (col-12).

Code

<!-- Colonnage par facette -->
<dsfr-data-facets id="filtered" source="src"
  server-facets
  fields="nom_region, cat_vehicule_libelle, cat_energie_libelle"
  labels="nom_region:Region | cat_vehicule_libelle:Type | cat_energie_libelle:Energie"
  display="nom_region:multiselect | cat_vehicule_libelle:select"
  cols="nom_region:6 | cat_vehicule_libelle:4 | cat_energie_libelle:12"
  max-values="8">
</dsfr-data-facets>

<!-- Colonnage global (toutes les facettes en col-6) -->
<dsfr-data-facets id="filtered" source="src"
  server-facets
  fields="nom_region, cat_vehicule_libelle, cat_energie_libelle"
  cols="6">
</dsfr-data-facets>