République
française
dsfr-data
Documentation — Web Components DSFR pour la dataviz
Composant visuel intermediaire qui affiche un champ de recherche DSFR et filtre les données en amont avant de les redistribuer aux composants en aval.
Visuel et intermediaire : Ce composant affiche un champ de recherche
ET redistribue les données filtrees aux composants en aval via le système d'événements.
Il se combine naturellement avec dsfr-data-facets.
dsfr-data-source → dsfr-data-normalize → dsfr-data-search → dsfr-data-facets → dsfr-data-display / dsfr-data-list
La recherche reduit le jeu de données, les facettes affinent ensuite. Les compteurs de facettes se recalculent dynamiquement.
| Attribut | Type | Défaut | Description |
|---|---|---|---|
id | String | - | Requis. Identifiant de la sortie (données filtrees). |
source | String | "" | ID de la source de données a ecouter |
fields | String | "" | Champs sur lesquels rechercher (virgule-séparés). Vide = tous les champs |
placeholder | String | Rechercher\u2026 | Placeholder du champ de saisie |
label | String | Rechercher | Label du champ (accessible) |
debounce | Number | 300 | Délai en ms avant déclenchement du filtre après la dernière frappe |
min-length | Number | 0 | Nombre minimum de caractères avant déclenchement |
highlight | Boolean | false | Ajoute un champ _highlight à chaque record avec les termes trouvés marqués en <mark> |
operator | SearchOperator | contains | Mode de recherche quand elle est calculée dans le navigateur, casse et accents ignorés : contains (le terme est une sous-chaîne), starts (un mot commence par le terme), words (tous les mots du terme sont présents). Une recherche confiée à un serveur (server-search, ou cible de context dont l'API a de quoi chercher) suit la comparaison de ce serveur. |
sr-label | Boolean | false | Si true, le label est en sr-only (visuellement masque, accessible) |
count | Boolean | false | Affiche un compteur de résultats sous le champ (compte serveur meta.total en server-search), séparateur de milliers français (#728). Ce compteur reste visible dès qu'une donnée a circulé ; seule sa nature de région live dépend de la chaîne aval (#654). Tant que l'amont attend un filtre (require-where), il cède la place au message d'attente : annoncer « 0 résultats » avant toute requête laisserait croire à une page vide. |
count-label | String | "" | Nom compté par le compteur de count, à la place de « résultat » : count-label="établissement" affiche « 12 345 établissements ». Une forme seule prend un « s » au pluriel ; pour un pluriel irrégulier, donner les deux formes séparées par une barre verticale : count-label="cheval|chevaux", count-label="prix|prix". |
url-search-param | String | "" | Nom du paramètre d'URL à lire comme terme de recherche initial. Vide = désactivé |
url-sync | Boolean | false | Synchronise l'URL quand l'utilisateur tape (replaceState) |
server-search | Boolean | false | Active le mode recherche serveur. Au lieu de filtrer localement, envoie une commande { where } au source upstream (dsfr-data-query server-side) qui re-fetche les données avec le filtre search. |
search-template | String | "" | Template pour la recherche serveur. {q} est remplacé par le terme de recherche, {fields} par les champs de fields séparés par | (#1026) — la grammaire colon des champs multiples, un OU entre eux. Si vide et server-search activé, lu depuis l'adaptateur de la source amont (gabarit par défaut de chaque adaptateur déclarant serverSearch : recherche plein texte native, ou {fields}:contains:{q} traduit en OU entre colonnes — la casse et les accents suivent l'API ; table des capacités d'ARCHITECTURE). Ex. personnalisés : '{q} IN nom', 'nom|commune:contains:{q}'. Une clause que l'adaptateur ne sait pas transmettre (caractère que son API ne sait pas porter), ou une source sans adaptateur, retombe sur une recherche locale, signalée en console. |
context | String | "" | Id du dsfr-data-context auquel s'enregistrer (#678, ADR-104) : la recherche est confiée au contexte, qui la diffuse à ses cibles et porte l'URL (url-sync et url-search-param sont ignorés — le paramètre est nommé d'après le champ, ou via url-param-map du contexte). fields doit nommer UN seul champ (le OU entre champs, a|b:contains:q #1026, reste propre à server-search). Le contexte peut être déclaré après la recherche dans la page. Vide = comportement autonome. La recherche n'est pas un filtre contains (ADR-159) : CHAQUE CIBLE LA TRADUIT, selon ce que son API sait faire. - Opendatasoft : le moteur de recherche du portail, borné au champ (search(champ, "terme")) — par DÉBUT DE MOT, casse et accents ignorés : « aliment » trouve « alimentation », « mentation » non. Le champ doit être du texte. - Tabular, Grist : une sous-chaîne (champ:contains:terme), casse ignorée, accents respectés. - INSEE Melodi, adaptateur tiers : la source calcule la recherche dans le navigateur, sur les lignes chargées (dans la limite de max-records), avec operator, casse et accents ignorés. Confiée à l'API, la recherche entre dans le where de la source : une cible en server-side et des facettes server-facets voisines comptent le même ensemble. Ce composant laisse alors passer les lignes de sa source sans les refiltrer, et son compteur (count) annonce le total du serveur. Calculée dans le navigateur, elle exige que la source charge le jeu : une cible en server-side passe en erreur de configuration. |
idle-message | String | IDLE_MESSAGE_DEFAULT | Message rendu quand l'amont attend un filtre (require-where, #690). Distinct de « aucune donnée » : aucune requête n'a été faite. Vide, le libellé par défaut est utilisé. |
En server-search, le gabarit search-template accepte {fields} :
il devient les champs de fields séparés par |, la grammaire des champs
multiples (nom|commune:contains:martin, un OU entre les champs). C'est le gabarit par
défaut sur Tabular, {fields}:contains:{q}, traduit en
or=(nom__contains.martin,commune__contains.martin) : le compteur lit le total serveur,
juste sur tout le jeu et non sur les lignes chargées. fields est alors obligatoire.
Côté serveur, contains est insensible à la casse mais sensible aux accents ; la
recherche locale, elle, les ignore — on ne l'aligne pas, pour ne pas rendre deux compteurs
différents selon le chemin. Un terme que l'API ne sait pas transmettre (,
. ( ) " & sur Tabular) retombe sur
une recherche dans le navigateur, sur les seules lignes chargées, et un avertissement le dit.
Avec context="id", la recherche est confiée au dsfr-data-context, qui la
diffuse à ses sources cibles, porte l'URL et le tag « Recherche : terme ». Ce n'est
pas un filtre contains : un filtre est une règle exacte écrite par
l'intégrateur, une recherche est ce que tape un visiteur. Le contexte porte le terme, le champ unique
de fields et operator, et chaque source cible traduit la
recherche selon ce que son API sait faire.
| Source cible | Qui cherche | Comparaison |
|---|---|---|
| Opendatasoft | le moteur du portail, borné au champ : search(champ, "terme") |
par début de mot, casse et accents ignorés : « aliment » trouve « alimentation », « mentation » non. Le champ doit être du texte. |
| Tabular, Grist | l'API : champ:contains:terme |
sous-chaîne, casse ignorée, accents respectés |
| INSEE Melodi, adaptateur tiers | la source, dans le navigateur | sur les lignes chargées (sous max-records), avec operator, casse et accents ignorés |
| source en mode URL | personne : la commande est refusée, et signalée en console | brancher la recherche sur cette source, sans context |
Confiée à l'API, la recherche entre dans le where de la source : une cible en
server-side pagine les seules lignes trouvées, et des
dsfr-data-facets server-facets voisines comptent le même ensemble. Le composant laisse
alors passer les lignes de sa source sans les refiltrer, et son compteur (count) annonce
le total du serveur. Calculée dans le navigateur, elle exige que la source charge le jeu : une cible en
server-side, ou des server-facets voisines, passent en erreur de
configuration. Le résultat n'est donc pas identique d'un fournisseur à l'autre ; c'est ce tableau qui
le dit.
Quand la source échoue, le champ est désactivé (lecture seule,
aria-disabled, toujours atteignable au clavier) sous la phrase « Filtres
momentanément indisponibles. », et le compte de résultats n'est plus affiché. Le terme déjà
saisi est gardé : il s'applique de nouveau au retour des données. La touche Échap efface
toujours le terme. Voir Quand la source est en panne.
Quand l'amont porte require-where, aucune requête n'est partie : le compteur de
count céderait la place à un « 0 résultat » trompeur. Il est remplacé par le texte de
idle-message (« Choisissez un filtre pour afficher les données » par défaut), qui dit
que rien n'a encore été demandé. Le champ de saisie, lui, reste utilisable — c'est souvent lui qui
pose le premier filtre et débloque la source. Le mécanisme est décrit sur
dsfr-data-source.
Modes de recherche :
contains (défaut) : sous-chaine insensible a la casse et aux accents.
starts : chaque mot du champ doit commencer par le terme.
words : tous les mots saisis doivent être présents (dans n'importe quel champ, n'importe quel ordre). Le plus utile pour la recherche multi-criteres.
Recherche textuelle sur les champs Produit, Marque et Catégorie.
Le tableau se filtre en temps réel avec un compteur de resultats.
<dsfr-data-search id="searched" source="clean"
fields="Produit, Marque, Catégorie"
placeholder="Produit, marque ou catégorie..."
operator="words"
min-length="2"
count>
</dsfr-data-search>
<dsfr-data-list source="searched"
columns="Produit, Catégorie, Marque, Date"
sort="Date:desc"
pagination="10">
</dsfr-data-list>
La recherche et les facettes se combinent. La recherche reduit le jeu de données, les facettes affinent. Les cartes affichent les resultats.
{{Marque}}
<dsfr-data-search id="searched" source="clean"
fields="Produit, Marque, Catégorie"
placeholder="Rechercher un produit rappele..."
operator="words"
count>
</dsfr-data-search>
<dsfr-data-facets id="filtered" source="searched"
fields="Catégorie, Marque"
labels="Catégorie:Catégorie | Marque:Marque"
max-values="6">
</dsfr-data-facets>
<dsfr-data-display source="filtered" cols="3" pagination="9">
<template>
<div class="fr-card">
<div class="fr-card__body">
<div class="fr-card__content">
<h3 class="fr-card__title">{{Produit}}</h3>
<p class="fr-card__desc">{{Marque}}</p>
</div>
<div class="fr-card__footer">
<p class="fr-badge fr-badge--sm">{{Catégorie}}</p>
</div>
</div>
</div>
</template>
</dsfr-data-display>
Les KPI et le graphique se recalculent en temps réel selon la recherche. Rechercher par nom d'entreprise, département ou region.
<dsfr-data-search id="searched" source="clean"
fields="Entreprise, Region, Departement"
placeholder="Entreprise, region, departement..."
operator="words"
count>
</dsfr-data-search>
<dsfr-data-kpi source="searched" value="count" label="Projets" color-token="bleu"></dsfr-data-kpi>
<dsfr-data-kpi source="searched" value="montant_investissement:sum" label="Investissement" format="euro"></dsfr-data-kpi>
<dsfr-data-query id="stats" source="searched"
group-by="Region"
aggregate="nombre_beneficiaires:sum:Beneficiaires"
order-by="Beneficiaires:desc"
limit="10">
</dsfr-data-query>
<dsfr-data-chart source="stats" type="bar"
label-field="Region"
value-field="Beneficiaires"
selected-palette="categorical">
</dsfr-data-chart>
En plus de la ré-émission des données filtrées sur le data-bridge sous son propre
id (dsfr-data-loaded / -loading / -error),
le composant émet un événement custom à chaque recherche effective :
| Événement | detail | Description |
|---|---|---|
dsfr-data-search-change |
{ sourceId, term, count } |
Émis sur document (bubbles, composed) après application d'un terme :
sourceId = id du composant, term = terme recherché,
count = nombre de résultats. |
document.addEventListener('dsfr-data-search-change', (e) => {
const { sourceId, term, count } = e.detail;
console.log(`${count} résultats pour « ${term} » (${sourceId})`);
});