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

19mar/095

Flex Item Renderer – Créer un ItemRenderer réutilisable avec listData

Voici la suite de la traduction de l'article de Peter Ent. On va maintenant parler de la création d'ItemRenderers réutilisables (génériques). Pour créer ces itemRenderer génériques, on va faire abstraction des champs sur lesquels on cherche les propriétés. Vous verrez qu'en passant par listData et en remontant un peu la chaîne, on peut récupérer l'information qui nous convient sans mettre de valeur "en dur".

Voici un exemple qui affiche une valeur numérique en utilisant un CurrencyFormatter. Celui-ci va simplement arrondir notre valeur pour qu'elle ait uniquement 2 chiffres après la virgule. Cet ItemRenderer peut être intéressant pour afficher un prix par exemple.

Voici donc le code de l'itemRenderer PriceFormatter:

<?xml version="1.0" encoding="utf-8"?>
<mx:Text xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
		<![CDATA[
			import mx.controls.dataGridClasses.DataGridListData;

			[Bindable] private var formattedValue:String;

			override public function set data(value:Object):void
			{
				super.data = value;

				formattedValue = cfmt.format( Number(data[(listData as DataGridListData).dataField]) );

			}
		]]>
	</mx:Script>

	<mx:CurrencyFormatter precision="2" id="cfmt" />

	<mx:text>{formattedValue}</mx:text>

</mx:Text>

Le point-clé de cet ItemRenderer est la partie indiquée en orange, qui modifie la variable bindable formattedValue. Tout d'abord, vous pouvez voir que le <mx:CurrencyFormatter> a été défini grâce à un tag MXML (vous pourriez le faire en ActionScript si vous le souhaitiez) avec l'id "cfmt". Dans cet exemple, formattedValue est donnée par le résultat de l'appel à la fonction format() du CurrencyFormatter.


Cette fonction prend un Number en paramètre, donc la valeur est cast en Number car le dataProvider de cet exemple est XML et dans du XML, tout est interprété comme du texte. Si vous utilisez un Object pour votre data ayant de vraies valeurs numériques, le cast en Number ne sera pas génant.

Comme vous le savez si vous avez lu les articles sur les itemRenderer, "data" est la propriété qui détient la donnée de l'item affiché par l'itemRenderer Flex. La notation [ ] est une autre manière d'accéder aux champs d'un item "data". Par exemple, data['price'] serait la colonne "price". Mais pour rendre cet itemRenderer, on ne doit pas coder pour un champ spécifique, il nous faut donc une manière plus générique.

Et c'est la que listData arrive. Tous les composants Flex qui implémentes l'interface IDropInListItemRenderer ont une propriété listData.

La plupart des composants comme Text, Label, Button, CheckBox etc. implémentent  l'interface IDropInListItemRenderer. La plupart des conteneurs comme HBox, Canvas etc. n'implémentent pas cette interface. Si vous voulez utiliser listData dans un itemRenderer qui hérite d'un Container, vous devrez implémenter IDropInListItemRenderer par vous même.

Cette propriété listData d'un itemRenderer contient entre autres, le rowIndex et le composant Flex qui utilise l'itemRenderer (la DataGrid, la List ou la TileList par ex.). Lorsque vous avez un itemRenderer utilisé dans une DataGrid, la propriété listData est en fait un objet DataGridListData, qui inclut le columnIndex et le dataField associé à la DataGridColumn.

Voici le découpage de l'expression en orange dans l'exemple, en partant du niveau le plus bas:

  • listData as DataGridListData: Cette ligne cast la listeData en objet DataGridListData pour avoir accès à la propriété dataField
  • .dataField: Le champ de colonne qui est concernée. C'est ce qui rend l'itemRenderer générique. Vous pouvez utiliser cet itemRenderer pour de multiples colonnes sans vous soucier du nom du champ.
  • data[...]: On accède à la donnée du champ spécifique pour cet item (notre nombre à formatter ici).
  • Number(...):On fait un cast de la valeur en Number pour être sûr car la fonction format() requiert un paramètre de type Number
  • cfmt.format ( ... ): On formatte notre valeur comme un prix

Voici un exemple d'utilisation:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="srcview/index.html">
	<mx:VBox>
		<mx:DataGrid editable="false">
			<mx:columns>
				<mx:DataGridColumn headerText="Titre" dataField="title"/>
				<mx:DataGridColumn headerText="Artist" dataField="artist"/>
				<mx:DataGridColumn headerText="Prix" dataField="price" itemRenderer="PriceFormatter"/>
				<mx:DataGridColumn headerText="Prix Soldé" dataField="soldPrice" itemRenderer="PriceFormatter"/>
			</mx:columns>
			<mx:dataProvider>
				<mx:ArrayCollection>
					<mx:Array>
						<mx:Object songId="0" title="Astronaut" artist="David Byrne" price="10.8743" soldPrice="8.4"/>
						<mx:Object songId="1" title="Rio" artist="Duran Duran" price="9" soldPrice="7.345"/>
						<mx:Object songId="2" title="Enjoy The Silence" artist="Depeche Mode" price="7.4322" soldPrice="4.9"/>
						<mx:Object songId="3" title="Mesopotamia" artist="B-52s" price="8.3" soldPrice="5"/>
					</mx:Array>
				</mx:ArrayCollection>
			</mx:dataProvider>
		</mx:DataGrid>
	</mx:VBox>
</mx:Application>

Flex Source Code Download: Télécharger le code source complet de l'application

This movie requires Flash Player 11

Articles similaires

Commentaires (5) Trackbacks (0)
  1. Vraiment parfait ! Merci

  2. Bonjour,

    Un petit commentaire simplement pour dire merci car ce tutoriel (ainsi que beaucoup d'autres sur votre blog) m'a été très utile !

    Wyndie

  3. Encore une fois : merci pour ce site! C'est une source d'information très appréciable.

  4. Hello,

    Je préfère l'ActionScript au MXML. Voici donc ma contribution :

    Actionscript:
    1. package Classes
    2. {
    3.     // Auteur: Denis BEURIVE
    4.    
    5.     import flash.events.Event;
    6.     import flash.events.MouseEvent;
    7.    
    8.     import mx.containers.Box;
    9.     import mx.controls.Button;
    10.     import mx.controls.TextArea;
    11.     import mx.controls.dataGridClasses.DataGridListData;
    12.     import mx.controls.listClasses.BaseListData;
    13.     import mx.controls.listClasses.IDropInListItemRenderer;
    14.     import mx.events.FlexEvent;
    15.  
    16.     // Consultez la documentation:
    17.     // DataGrid =&gt; DataGridItemRenderer (Implements) =&gt; IDataRenderer (Implementors) =&gt; Container (Subclasses) =&gt; Box
    18.     // IDropInListItemRenderer: BaseListData et DataGridListData
    19.  
    20.     public class MyItemRenderer extends Box implements IDropInListItemRenderer
    21.     {
    22.         // Cette propriété est utilisée pour implémenter l'interface "IDropInListItemRenderer".
    23.         private var _listData:BaseListData;
    24.        
    25.         // Ce bouton est utilisé pour rendre le composant interactif.
    26.         private var __bouton:Button = new Button();
    27.        
    28.         // Cette propriété est utilisée pour illustrer l'usage de la propriété "properties" de la classe "ClassFactory".
    29.         // var fac:ClassFactory;
    30.         // fac = new ClassFactory(Classes.MyItemRenderer);
    31.         // fac.properties = { butonLabel:'Press' };
    32.         public  var butonLabel:String;
    33.        
    34.         // Affichage des informations fournies par la grille d'affichage "DataGrid".
    35.         private var __text:TextArea = new TextArea();
    36.        
    37.        
    38.         public function MyItemRenderer()
    39.         {
    40.             super();
    41.             __setSeventHandlers();
    42.             __createInterface();
    43.         }
    44.        
    45.         private function __createInterface():void
    46.         {
    47.             this.addChild(__bouton);
    48.             this.addChild(__text);
    49.         }
    50.        
    51.         private function __setSeventHandlers():void
    52.         {
    53.             this.addEventListener(FlexEvent.INITIALIZE, __init);
    54.             __bouton.addEventListener(MouseEvent.CLICK, __printDataGridInfo);
    55.         }
    56.        
    57.         private function __init(event:Event):void
    58.         {
    59.             __bouton.label = butonLabel;
    60.         }
    61.        
    62.         private function __printDataGridInfo(event:Event):void
    63.         {
    64.             __text.htmlText = '<b>Rox index</b>: '    + this._listData.rowIndex'' +
    65.                               '<b>Column index</b>: ' + this._listData.columnIndex;
    66.         }
    67.        
    68.         // Implémentation de l'interface "IDropInListItemRenderer".
    69.         public function get listData():BaseListData
    70.         {
    71.             return _listData;
    72.         }
    73.    
    74.         // Implémentation de l'interface "IDropInListItemRenderer".
    75.         public function set listData(value:BaseListData):void
    76.         {
    77.             _listData = value;
    78.         }
    79.  
    80.        
    81.     }
    82. }

    Et:

    MXML:
    1. Implementors =&gt; Container =&gt; Subclasses =&gt; Box
    2.        
    3.             import Classes.MyItemRenderer;
    4.             import mx.controls.dataGridClasses.DataGridColumn;
    5.             import mx.collections.XMLListCollection;
    6.             import mx.controls.DataGrid;
    7.  
    8.             private var __xml:XML = 
    9.                                        
    10.                                        
    11.                                        
    12.                                     ;
    13.             private var __grid:DataGrid = new DataGrid();
    14.  
    15.             private function __initComplete():void
    16.             {
    17.                 var c1:DataGridColumn = new DataGridColumn();
    18.                 var c2:DataGridColumn = new DataGridColumn();
    19.                 var c3:DataGridColumn = new DataGridColumn();
    20.                 var c4:DataGridColumn = new DataGridColumn();
    21.                 var fac:ClassFactory;
    22.  
    23.                 __grid.dataProvider = new XMLListCollection(__xml.line);
    24.                 fac = new ClassFactory(Classes.MyItemRenderer);
    25.                
    26.                 // La classe "MyItemRenderer" implémente l'interface "IDropInListItemRenderer".
    27.                 // La propriété "listData" sera automatiquement renseignée.
    28.                 fac.properties = { butonLabel:'Press' };
    29.  
    30.                 c1.dataField    = '@col1';    c1.headerText = 'Région';
    31.                 c2.dataField    = '@col2';    c2.headerText = 'Ville';
    32.                 c3.dataField    = '@id';      c3.headerText = 'Id';
    33.                 c4.itemRenderer = fac;        c4.headerText = 'Action';
    34.  
    35.                 __grid.dataProvider = new XMLListCollection(__xml.line);
    36.                 __grid.columns      = [ c1, c2, c3, c4 ];
    37.  
    38.                 this.addChild(__grid); 
    39.             }
    40.            
    41.         ]]&gt;

    A+

  5. Denis, merci pour ta contribution, cela m'a beaucoup aidé dans mon projet.


Leave a comment

(required)

Aucun trackbacks pour l'instant