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

20sept/091

Flex ArrayCollection – FilterFunction avec plusieurs functions (Comparatif de 5 méthodes)

L'objet ArrayCollection est souvent utilisé comme dataProvider pour remplir des List, des DataGrid, des AdvancedDataGrid et bien d'autres. Pour faire simple, c'est une Array amélioré, qui propage des évènements lors de sa modification et permet donc d'avoir un DataBinding (liaison) entre cet objet et le dataProvider.

Fonctionnement basique de filterFunction sur ArrayCollection

L'objet ArrayCollection propose une propriété nommée "filterFunction" permettant de filtrer la liste selon certains critères de votre choix. Il faut pour cela assigner une fonction de callback qui va renvoyer un Boolean. La signature de la fonction filterFunction est la suivante:

public function filterFunction(item:Object):Boolean{
	// votre code
}

Quand Flex va faire une mise à jour du dataProvider (comme un refresh() sur l'objet ArrayCollection), pour chaque élément il va appeler cette fonction. Il va passer l'élément parcouru comme paramètre de cette fonction, c'est-à-dire le paramètre "item". Si cette fonction retourne "true", l'élément ne sera pas filtré et sera donc affiché. Si elle renvoie false, l'élément sera filtré et ne sera pas affiché.

Si vous voulez mettre à jour les éléments filtrés, il vous suffit de mettre à jour le dataProvider en appelant sa méthode myArrayCollection.refresh(). Pour ne filtrer aucun élément, mettez la propriété filterFunction à null.

Comment filtrer un ArrayCollection sur plusieurs critères ?

Avec des données parfois complexes, de multiples champs et parfois des types de données qui ne sont pas des types de base, vous allez peut-être vouloir créer un filtrage plus complexe, sur plusieurs champ ou sur plusieurs valeurs. Je vais exposer ici plusieurs méthodes dont une que j'ai mise au point moi-même. A vous de faire votre choix suivant la complexité de votre application ;) .

Méthode 1 – La méthode triviale (mais robuste)

Admettons que vous ayez maintenant une DataGrid ou ADG complexe et que vous vouliez filtrer les éléments sur plusieurs critères. Vous pouvez faire une fonction filterFunction avec un code interne complexe comme ceci:

public function filterFunction(item:Object):Boolean{
	var price:int = int(item.price);
	var product:String = item.product;
	if (price > 20 && product != "ColdFusion"){
		return true;
	}
	return false;
}

Cette méthode de filtre ne laisserai que les éléments donc le champ prix est supérieur a 20 et dont le nom n'est pas "ColdFusion". On filtre ici selon deux critères simples avec des valeurs fixes. On peut mettre les valeurs de comparaison (20 et ColdFusion) comme variable de la classe pour pouvoir être modifiées dynamiquement mais si par exemple vous voulez trier selon un autre champ, il vous faut créer une nouvelle filterFunction sur 3 champs et vous allez vite vous rendre compte que cette méthode n'est pas viable car trop robuste. Si on y réfléchit, le plus simple serait d'assigner plusieurs fonctions de type filterFunction. Or, ArrayCollection permet seulement d'assigner une seule filterFunction. Les méthodes suivantes tentent de résoudre ce problème.

Méthode 2 – Créer une sous-classe de ArrayCollection et ajouter une propriété filterFunctions

Voici une méthode que propose Cristian Rotundu sur son blog. Cette méthode consiste à créer un composant qui hérite d'ArrayCollection (baptisé ArrayCollectionExtended) pour pouvoir ajouter une propriété filterFunctions. Cette propriété prend en paramètre un Array (tableau) de fonction qui vont chacune filtrer la data. Si l'une de ces fonctions renvoie false pour un élément, il sera filtré.

Voici comment il est utilisé dans une application:

someArrayCollection.filterFunctions =
	[ 	filterByVendor, filterByPrice,
		filterByTime, filterByEventType,
		filterByKeywords
	];	

someArrayCollection.refresh();

Cette méthode fonctionne bien mais elle reste cependant assez contraignante. Tout d'abord, le fait d'hériter d'ArrayCollection est pratique dans ce cas mais si vous utilisez de nombreuses ArrayCollection dans votre application, il vous faudra remplacer toutes vos déclarations par ce nouveau type. Et si vous utilisiez déjà une classe héritant d'ArrayCollection, comme vous ne pouvez pas faire d'héritage multiple en AS3, il va falloir bricoler.

Voir l'exemple d'application de cette méthode