Blazor : créer un composant avec une datagrid (3/3) : les filtres

Blazor sqli 3

Cette troisième et dernière partie de mon article dédié à Blazor se concentre sur l’ajout de filtres sur le composant Datagrid. Je vais repartir du composant déjà produit jusque-là. Si ce n’est pas fait, je vous invite à lire les deux précédentes parties de l’article, ce qui vous permettra de suivre plus aisément cette partie. A la fin de la partie 2, nous avions un composant affichant une datagrid paginée et triée ; il est temps de pouvoir filtrer les colonnes. 

 

Filtrer les colonnes 

Pour réaliser le filtre, nous allons ajouter une zone de saisie dans chaque colonne. La saisie déclenchera l’appel d’une fonction qui modifie la liste en fonction du filtre.  

Par ailleurs, il faudra que ce filtre tienne compte des valeurs de chaque colonne. Pour réaliser un filtre tenant compte des valeurs des zones de saisie de chaque colonne, il faut introduire un dictionnaire au niveau du composant parent. Ce dictionnaire stockera le nom de la colonne et la valeur du filtre. 

1.  Dans le fichier BlazorDataGrid.razor ajoutez :  

public Dictionary<string, string> FilterDictionary { get; set; } 

2. Dans la fonction OnInitializedAsync, on initialise le dictionnaire : 

FilterDictionary = new Dictionary<string, string>(); 

3. Dans le fichier DataGridColumn.razornous avons besoin d’une fonction de filtre. Ajoutez : 

private void Filtering(string value, string columnName) 

    { 

        BlazorDataTable.FilterDictionary[columnName] = value; 

 

        foreach (var column in BlazorDataTable.FilterDictionary) 

        { 

            BlazorDataTable.Items = BlazorDataTable.Items.Where(x => x.GetType().GetProperty(column.Key).GetValue(x, null).ToString().IndexOf(column.ValueStringComparison.OrdinalIgnoreCase) >= 0).ToList(); 

        } 

 

        AppState.CallRequestRefresh(); 

    } 

 

Cette fonction prend deux paramètres : le nom de la colonne dans laquelle vient d’être saisi un filtre et la valeur saisie. 

La première instruction consiste à ajouter dans le tableau (ou modifier si la clé existe déjà) la valeur associée à la colonne. Ensuite, on itère sur chaque colonne présente dans le dictionnaire pour affiner le filtre. A la fin, la liste parente est modifiée avec uniquement les valeurs correspondantes à l’ensemble des filtres. 

Et la dernière instruction, tout comme avec le tri, indique au parent qu’il faut mettre à jour son affichage. 

 

4. La fonction est en place, il faut à présent ajouter la zone de saisie du filtre. Dans la balise th, ajoutez : 

<br /> 

 <input width="70" @oninput="@((ui) => { Filtering((string)ui.ValueColumnName); })" /> 

On place une balise input qui sera notre zone de saisie, et sur l’évènement oninput (à chaque fois que l’on tape quelque chose dans la zone de saisie) on appelle la fonction de filtrage avec les paramètres requis. On a donc : 

<th> 

        <span @onclick="@(() => SortTable(ColumnName))">@DisplayColumnName</span> 

        <span class="oi @(GetSortStyle(ColumnName))"></span> 

        <br /> 

        <input width="70" @oninput="@((ui) => { Filtering((string)ui.ValueColumnName); })" /> 

    </th> 

A l’exécution, on constate que le filtre fonctionne bien. Il y a malgré tout un léger petit souci : une fois filtré, on ne peut pas revenir en arrière. En effet, si j’enlève un caractère saisi dans l’une des zones de filtre, je ne reviens pas à l’état filtré précédent. Ceci s’explique simplement parce que notre liste filtrée ne contient plus tous les éléments. Il faut donc introduire un mécanisme de retour arrière afin de pouvoir ajuster le filtre sans perte de données. 

 

5. Nous allons donc ajouter une variable dans le fichier DataGridColumn.razor : 

private string PreviousValue { get; set; } = string.Empty; 

Cette variable nous permet de connaitre la précédente valeur tapée pour la colonne. Si sa taille est inférieure à la nouvelle valeur, c’est qu’on fait un retour arrière et qu’il faut reprendre une liste plus étendue. 

 

6. Dans notre fonction de filtrage, on va ajouter un test : 

if (value.Length < PreviousValue.Length) 

        { 

            BlazorDataTable.Items = Items; 

        }

On reprend la liste de départ si on enlève des caractères. 

 

7. A la fin, on met à jour la valeur de la variable PreviousValue : 

PreviousValue = value; 

La fonction de filtrage ressemble maintenant à ça : 

private void Filtering(string value, string columnName) 

    { 

        BlazorDataTable.FilterDictionary[columnName] = value; 

 

        if (value.Length < PreviousValue.Length) 

        { 

            BlazorDataTable.Items = Items; 

        } 

 

        foreach (var column in BlazorDataTable.FilterDictionary) 

        { 

            BlazorDataTable.Items = BlazorDataTable.Items.Where(x => x.GetType().GetProperty(column.Key).GetValue(x, null).ToString().IndexOf(column.ValueStringComparison.OrdinalIgnoreCase) >= 0).ToList(); 

        } 

 

        AppState.CallRequestRefresh(); 

        PreviousValue = value; 

    } 

On constate maintenant que le filtre revient bien en arrière si on enlève des caractères. 

 

Conclusion 

L’utilisation de composants imbriqués enrichit considérablement le comportement des éléments. On a pu constater dans cet exemple qu’il est facile d’ajouter un filtre sur une colonne en améliorant simplement son composant. L’imbrication n’a pas de limite ; on peut donc réaliser des composants complexes permettant de répondre à des besoins complexes. 

Blazor permet ainsi de réaliser facilement des composants réutilisables en s’appuyant uniquement sur du code C#. Il n’est ainsi plus obligatoire d’avoir recours à du javascript. Et comme le montre cet exemple, on peut s’appuyer sur la richesse du .net pour faire des pages web interactives. 

 

Retrouvez les précédentes parties :  

0 commentaires

votre commentaire

Se joindre à la discussion ?
Vous êtes libre de contribuer !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Inscription newsletter

Ne manquez plus nos derniers articles !