2
votes

Filtre personnalisé AgGrid non créé avant l'interaction

J'ai un composant de filtre personnalisé sur une colonne de ma grille. J'ai remarqué que le composant de filtre n'est pas construit tant que je n'ai pas cliqué sur l'icône de filtre dans l'en-tête de colonne. Cela signifie que les données ne sont pas filtrées selon mes paramètres par défaut (par exemple, filtrer les enregistrements où status == StatusEnum.Complete ).

Pour contourner le problème, j'ai constaté que je pouvais obtenir une instance de filtre dans l'événement onGridReady en appelant api.getFilterInstance ('status') , et cela provoque le composant de filtre à créer et appliquer ainsi le filtrage par défaut.

Cette solution de contournement semble un peu maladroite. La variable filter n'est pas utilisée dans l'événement onGridReady , ce qui provoque des avertissements dans l'EDI / build. Un autre développeur peut venir et supprimer cette ligne de code, pensant que ce n'est pas nécessaire.

Existe-t-il un meilleur moyen de forcer mon filtre personnalisé à être instancié lorsque la grille est créée? J'utilise AgGrid 17.1 et Angular 4.4.

La grille est configurée comme ceci:

gridOptions: GridOptions = {
    enableFilter: true,
    onGridReady: (event) => {
        let filter = event.api.getFilterInstance("status"); // forces the filter component to be constructed
        let data = this.loadAsyncData();
        event.api.setRowData(data);
    },
    columnDefs: [
    ...
    {
        headerName: "Status",
        field: "status",
        filterFramework: MyCustomStatusFilterComponent,
        filterParams: {
            valueGetter: (obj) => { return obj.data.statusEnum; },
            hideCompleteByDefault: true,
            ...
        }
    },
    ....
    ]
}

J'ai mis en place un exemple illustrant le problème . Notez le "hack" à la ligne 63 de app.component.ts.


2 commentaires

Je suis en quelque sorte intéressé à regarder cela, mais vous n'avez pas de cas de test, ce qui rend difficile de vous aider. Pouvez-vous mettre en place une démonstration montrant le problème? Vous pouvez démarrer à partir de ce ou de tout autre exemple du documentation .


@thirtydot plunkr ajouté. Merci!


3 Réponses :


2
votes

Tout d'abord, ce sont deux choses indépendantes, le filtre personnalisé et l'initialisation du filtre.

Je suppose que vous avez mélangé ces deux phases et essayé d'obtenir un résultat inattendu.

Votre filtre personnalisé ne doit pas contenir de logique prédéfinie car init ne se produira qu’au premier contact de votre filtre , vous devez diviser votre logique puis en < code> onGridReady vous pouvez exécuter setModel avec les éléments nécessaires. ou gardez un hack comme vous l'avez déjà mentionné


2 commentaires

Cette approche semble fonctionner pour moi. Je suis cependant toujours curieux de savoir pourquoi les filtres ne sont pas initialisés tant qu'ils ne sont pas touchés pour la première fois. Est-ce quelque part dans la documentation ag-grid ?


@djs: Je ne peux pas le voir explicitement dans la documentation, mais cela n'a pas d'importance. Si vous regardez dans la source, c'est "initialiser à la demande", et c'est presque certainement pour des raisons de performances. Regardez la toute première fonctionnalité qu'ils répertorient: ag-grid.com/features-overview ("Performance exceptionnelle"). Pensez-y: le filtre défini doit passer par chacun de vos (définissez-le sur: 100 000) lignes pour collecter les valeurs uniques. Si vous en avez plus de 22 colonnes, la grille sera en retard au démarrage (en particulier sur un matériel lent).



1
votes

Le problème principal est que vous vous battez contre le fonctionnement par défaut des composants du filtre. Ag-grid fait un effort considérable pour créer l'interface graphique du filtre à la demande (lorsque vous cliquez sur l'icône du filtre de colonne). Ceci afin d'éviter que les performances ne soient affectées par l'initialisation inutile de 100 composants de filtre différents au démarrage de la grille (si vous avez 100 colonnes).

Si vous souhaitez conserver les paramètres de filtre (filtrez "Complet") à l'intérieur de votre composant de filtre personnalisé, puis restez fidèle à ce que vous avez. Je doute qu'il y ait un meilleur hack là-bas.

Cependant, ce que vous devriez faire est de déplacer la condition de filtre vers en dehors du composant de filtre personnalisé. Imaginez si vous avez une page différente, où vous souhaitez un filtrage différent sur la colonne Statut par défaut. Ce sera difficile de faire cela avec votre conception actuelle.

Votre code devrait ressembler davantage à ceci:

onGridReady(params) {
    this.gridApi = params.api;
    this.gridColumnApi = params.columnApi;

    // hack to get default filtering
    //params.api.getFilterInstance('status');

    params.api.setRowData(this.rowData);

    // apply filter model
    // use same filter model that enterprise set filter uses, since your filter is similar
    params.api.setFilterModel({
        status: {
            filterType: 'customStatusFilter',
            values: ['New', 'Working on it'],
        },
    });

    params.api.sizeColumnsToFit();
}

Bien sûr, pour utiliser ceci, vous devra réécrire substantiellement votre composant de filtre personnalisé. J'ai essayé de le faire, mais cela prenait trop de temps, et je ne connais pas vraiment Angular, donc je soumets ma réponse telle quelle. Votre implémentation actuelle vous posera beaucoup de problèmes si vous essayez de vous en servir (ou de la mélanger avec d'autres fonctionnalités d'ag-grid).

Ces liens vous aideront peut-être:


5 commentaires

La méthode isFilterActive () ne devrait-elle pas empêcher des centaines de vérifications lors de l'initialisation? Les filtres sans filtrage par défaut renverraient false. Pouvez-vous également expliquer votre dernière phrase? Votre implémentation actuelle vous posera beaucoup de problèmes si vous essayez de vous en inspirer (ou de la mélanger avec d'autres fonctionnalités d'ag-grid) J'utilise effectivement ceci avec succès dans plusieurs endroits avec des énumérations de statut différentes et options de filtrage par défaut.


Je dois également souligner que le plunkr que j'ai mis en place est un MCVE pour démontrer le problème du filtre non initialisé lors de la création de la grille. Mon code actuel a d'autres abstractions et modèles au travail qui le rendent plus réutilisable dans le cadre d'ag-grid.


Comment utilisez-vous différentes énumérations d'état lorsqu'elles sont codées en dur dans votre composant de filtre? Essayez de créer deux colonnes d'état différentes dans une grille sans dupliquer votre fichier de composant de filtre personnalisé. Essayez d'utiliser setFilterModel pour définir une plage de filtres sur votre grille. Essayez de réinitialiser tous les filtres pour qu'il n'y ait aucun filtrage. Essayez d'utiliser setColumnDefs pour ajouter une colonne supplémentaire à la fin. Qu'en est-il lorsque vous avez besoin de ce filtrage de style de case à cocher sur une colonne différente?


Il y a vraiment deux côtés à cela. D'une part, votre code fonctionne pour votre cas d'utilisation actuel. D'autre part, la plupart du code sur thedailywtf.com , ... jusqu'à ce que ce ne soit pas le cas. Le but de votre question était que vous n'aimiez pas votre "hack" et qu'un autre développeur pourrait le supprimer. Votre composant de filtre entier est un hack! Bien sûr, je le compare au filtre d'ensemble d'entreprise, ce qui est naturellement injuste. Si votre grille est le début d'un projet complexe, cela compte davantage. S'il ne s'agit que d'une page ponctuelle rapide, cela n'a pas vraiment d'importance. ¯ \ _ (ツ) _ / ¯


(J'ai écrit ces commentaires avant votre dernier commentaire).



0
votes

Ici, vous utilisez le filtrage personnalisé,

Si votre ligne n'est pas liée à une valeur, vous utilisez le filtrage personnalisé.

         {
            headerName: "Date",
            field: "date",

            //Custom  Filter Start

            filterValueGetter: (params: ICellRendererParams) => 
            {
              if (this.transactionIsEmpty(params.data)) 
              {
                const tx: Transaction = params.data;
                return moment(tx.date).format('DD-MM-YYYY');
              }
            },

            //Custom  Filter End

            cellStyle: { 'text-align': 'left' },
            minWidth: 250,
        }


0 commentaires