Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

27sept/0918

DataFilterLib – Filtrer plusieurs vues en utilisant le DataBinding

Voici un nouvel exemple de la DataFilterLib qui montre simplement comment on peut mettre à jour plusieurs vues avec un seul filtre. Dans cet exemple, j'ai 4 composants qui ont tous comme dataProvider, la même ArrayCollection. J'ai ainsi une DataGrid, une TileList, une List et un Chart qui affichent ma donnée (donnée d'exemples avec des appareils photo).

Pour effectuer mon filtrage, j'utilise un filtre de type INTERVAL, que vous pouvez configurer à votre guise. Cet article explique le fonctionnement des DataFilterInterval en détail. Grâce au mécanisme de Data Binding entre mes vues et mon model, toutes les vues vont se mettre à jour pendant la modification du filtrage.

Démonstration en ligne (onglet "Filter multiple views")

This movie requires Flash Player 11

Articles similaires

Commentaires (18) Trackbacks (0)
  1. Bonjour moi j'aurais une petite question :

    Comment intégrer les fonctionnalités de filtrage sur une dataGrid dont les données sont paginées (à l'aide du paginateur disponible sur ce site)?

  2. Salut Cédric,
    En voilà une question intéressante ^^. Je n'avais pas pensé à cumuler les deux mais cela doit être possible.
    Dans ton cas, c'est bien de la pagination côté client que tu veux faire? Parce que si la pagination est faîte côté serveur, cela signifie que tu n'aurais déjà qu'un sous ensemble de la donnée et donc le filtrage se ferait directement sur ce sous-ensemble.
    Mais je pense que tu veux filtrer côté client. Tu as donc toute la donnée côté client et tes filtres (DataFilter...). La pagination devient en fait un filtre supplémentaire, qui trie selon l'index de l'item (s'il est dans la page courante, c'est affiché, sinon c'est rejeté).
    Je n'ai pas encore essayé mais je pense que c'est possible. La seule embûche est qu'avec les filtres classiques (ceux des exemples, tu filtres selon un ou plusieurs champs de la donnée (paramètre filterKey). Ici, il va falloir que tu filtres par rapport à l'index de ton élément par rapport au dataProvider.
    Je vais essayer de bricoler un truc pour l'exemple. Si je réussis, j'en fait un billet sur le blog :)

    Fabien

  3. J'ai trouvé, le billet sera publié demain ;)

    Fabien

  4. Salut Fabien,

    Effectivement je parlais d'une pagination côté client (pour l'instant).

    J'ai essayé quelque chose : je filtre directement sur la liste (qui est le dataProvider de ma dataGrid).

    J'ai donc plusieurs problèmes :
    1 - Le nombre de pages ne se réajuste pas (on garde le nombre total de pages que l'on avait au début lorsque les données ne sont pas filtrées)

    2 - Lorsque le résultat du filtrage nécessite plusieurs pages (admettons grille de 25 lignes, et on a 30 éléments résultant du filtrage), pour avoir les 5 derniers éléments il faut que j'aille sur la page "2". et lorsque je clique sur la page "2", bah je me retrouve avec les données de la page 2 non filtrées. (les données de départ en fait).

    Voilà je sais pas trop si j'ai été clair.

    Pour résumer ce qu'il faudrait c'est :
    1 - adapter le nombre de page du paginateur en fonction du nombre d'éléments apparaissant dans la grille après filtrage

    2 - Peut-être récupérer dans une ArrayCollection le résultat du filtrage et re-binder avec la DataGrid?

    Merci pour cette lib et pour ta réactivité

    Cédric

  5. Salut Cédric,
    et bien au départ, j'ai eu les même problèmes que toi et la solution à adopter est bien la 2 ! (Peut-être récupérer dans une ArrayCollection le résultat du filtrage et re-binder avec la DataGrid?). Car si on rajoute la pagination comme un filtre supplémentaire, on ne pagine pas les éléments filtrés, on filtre encore plus et on perd la pagination.
    Il faut bien paginer les éléments filtrés. Et avec la méthode 2, cela fonctionne très bien avec adaptation du nombre de pages. Je poste le code ce soir

    Fabien

  6. Ok ça marche.
    Dans l'attente du code, si t'as le temps, pourrais-tu me donner la méthode qui te permet de récupérer le résultat des données filtrées?

    J'ai cherché, mais je ne trouve pas de méthode retournant une ArrayCollection avec les données filtrées :s

    Comme je suis au boulot c'est pour essayer d'avancer un peu donc en attendant le code si t'as le nom de la méthode.

    Si t'as pas le temps tant pis ça attendra lundi.

    En tout cas merci

    Ced

  7. Salut,
    le code est chez moi, c'est dommage, j'aurai du me le transférer. Je vais le faire de tête. En fait, il faut que tu ais une deuxième AC:

    Actionscript:
    1. private var _dataCopy:ArrayCollection = null;

    Et au creationComplete de ton application, tu vas copier ton AC de base (on va l'appeler "data") et t'insrire à son changement de data:

    Actionscript:
    1. private function onCreationComplete():void{
    2.   data.addEventListener(CollectionEvent.COLLECTION_CHANGE, onCollectionChanged);
    3.   copyCollection();
    4. }
    5.  
    6. private function onCollectionChanged(event:CollectionEvent):void{
    7.   copyCollection()
    8. }
    9.  
    10. private function  copyCollection():void{
    11.  var arrCopy:Array = ObjectUtil.copy(data.toArray()) as Array;
    12.  _dataCopy = new ArrayCollection(arrCopy);
    13. }

    Il me semble que j'ai oublié une ligne, mais ca doit être ça. Ensuite, tu auras dans _dataCopy, une copie de ta donnée filtrée. C'est cette donnée que tu devras paginer.
    Perso, j'ai paginé avec la DataFilterLib en créant un DataFilterIntervalPagination qui hérite de DataFilterInterval mais c'est un peu complexe car il faut que l'objet DataFilterIntervalPagination connaisse son dataProvider pour déterminer l'index de l'élément à filtrer. Tu peux faire plus simple en attendant, en travaillant sur ton _dataCopy

    Fab

  8. Ok merci je vais chercher et je te tiens au courant si j'y arrive (ou pas d'ailleurs :) )

  9. Re fab.

    En fait il y'a 2-3 choses que je n'ai pas compris. Je pensais avoir compris mais en fait ce n'est pas le cas.

    A priori ta librairie ne dispose pas de méthodes retournant la AC des éléments ainsi filtrés (tu m'arrêtes si je me trompe)

    Donc d'après ce que j'ai compris tu mets un genre d'espion sur la AC :
    #
    private function onCreationComplete():void{
    #
    data.addEventListener(CollectionEvent.COLLECTION_CHANGE, onCollectionChanged);
    #
    copyCollection();
    #
    }

    Et ceci afin de repérer dès que ta liste est modifiée (sous-entendu qu'elle est filtrée).
    Dans ce cas, on copie la nouvelle AC dans une sorte de liste tampon _dataCopy qui sera mise à disposition, je suppose, du dataProvider.

    Cependant à chaque fois que je démarre un filtrage, à priori il ne détecte pas les modifications de la liste initiale. Du coup, l'évènement "CollectionEvent.COLLECTION_CHANGE" n'est pas détecté, du coup la méthode "onCollectionChanged()" n'est pas appelée ce qui implique que je n'obtiens pas la liste données filtrées.

    Cependant je ne suis absolument pas sûr d'avoir bien compris je suis peut-être totalement hors sujet ce qui expliquerai alors pourquoi ca ne marche pas :) .

  10. Salut,
    effectivement, il n'y a pas de méthode qui retourne l'AC des éléments filtrés car si tu effectues un filtrage sur "data", et que tu vas récupérer les éléments de "data", tu auras uniquement les éléments filtrés par la filterFunction.
    Donc pour récupérer tes éléments filtrés, il te suffit de récupérer "data" !
    Par contre, c'est très étrange que l'évènement CollectionEvent.COLLECTION_CHANGE ne soit pas envoyé. Quand on filtre "data", on appelle la méthode refresh() à chaque fois qui va déclencher l'évènement.
    Tu es bien sûr que tu est inscrit au bon évènement sur "data" (pas sur la copie) avant le filtrage?

    Fabien

  11. Je crois que c'est parce que j'utilise cairngorm et que je travaille sur la liste directement renvoyée par le modelLocator c'est peut être ça qui pose problème.

    Je vais d'abord manger et je continue cet après-midi.

    Bon app!!!

  12. Alors avec Cairngorm, je ne peux pas t'en dire plus, jamais utilisé!

    Bon app ^^

  13. Ah quel moment il censé faire un data.refresh en fait?

    Lorsqu'on rentre une valeur à filtrer dans la "TextInput" des values à filtrer?
    A chaque caractère saisi il fait le .refresh?

  14. Oui, à chaque filtrage (modification de la recherche ou de l'intervalle), un refresh se produit. Sinon, tu peux essayer de faire un refresh() à la main sur ton AC pour t'assurer que ton évènement est bien lancé

    Fabien

  15. J'y arrive pas je pense que je vais attendre ton code.

    Tu vas mettre les 2? C'est-à-dire côté "mxml" et "as"? Ca peut-être intéressant de mettre aussi le mxml afin de voir les dataProvider etc...

  16. Oui oui, j'ai fait un petit projet juste pour le test. Encore quelques heures à patienter ^^

    Fabien

  17. Le truc qui est vraiment bizarre c'est qu'il ne détecte pas le filtrage. Je ne rentre jamais dans le handler onCollectionChanged(). Et pourtant tant que je n'ai pas changé de page, le filtrage a bien lieu comme je l'ai expliqué sur mon deuxième post.

    J'arrive pas à décrocher de ce truc sur lequel je galère depuis 3 jours :( .


Leave a comment

(required)

Aucun trackbacks pour l'instant