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

8mar/093

Flex Item Renderer – Utiliser la propriété itemEditor pour la mise à jour

Quand les composants sont éditables, ils utilisent des champs texte standard pour l'édition des valeurs. Par exemple, le code suivant crée une mx:List éditable simplement en fixant la propriété "editable" à true. Mais l'utilisateur peut seulement éditer les valeurs avec un champ text par défaut quand il clique sur un item:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="srcview/index.html">
	<mx:List editable="true" width="200" labelField="rating">
		<mx:dataProvider>
			<mx:ArrayCollection>
				<mx:Array>
					<mx:Object songId="0" title="Astronaut" artist="David Byrne" rating="0"/>
					<mx:Object songId="1" title="Rio" artist="Duran Duran" rating="2"/>
					<mx:Object songId="2" title="Enjoy The Silence" artist="Depeche Mode" rating="1"/>
					<mx:Object songId="3" title="Mesopotamia" artist="B-52s" inFavorites="true" rating="4"/>
				</mx:Array>
			</mx:ArrayCollection>
		</mx:dataProvider>
	</mx:List>
</mx:Application>

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

This movie requires Flash Player 11

Vous pouvez personnaliser la manière par laquelle un utilisateur peut éditer une valeur en utilisant un item editor. Pour assigner un "item editor", il faut utiliser la propriété itemEditor, comme vous le faîtes pour la propriété itemRenderer. Vous devez aussi spécifier une valeur à la propriété editorDataField pour dire au composant quel propriété de l'item renderer doit être liée au data provider. Dans l'exemple suivant, on a modifié le tag mx:List pour qu'il utilise un Numeric Stepper plutôt qu'un champ texte lorsqu'on passe en mode édition. Notez que l'on spécifie "value" comme editorDataField car "value" est le nom de la propriété du NumericStepper qui doit être liée au dataProvider.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="srcview/index.html">
	<mx:List editable="true" width="200" labelField="rating"
		itemEditor="mx.controls.NumericStepper" editorDataField="value">
		<mx:dataProvider>
			<mx:ArrayCollection>
				<mx:Array>
					<mx:Object songId="0" title="Astronaut" artist="David Byrne" rating="0"/>
					<mx:Object songId="1" title="Rio" artist="Duran Duran" rating="2"/>
					<mx:Object songId="2" title="Enjoy The Silence" artist="Depeche Mode" rating="1"/>
					<mx:Object songId="3" title="Mesopotamia" artist="B-52s" inFavorites="true" rating="4"/>
				</mx:Array>
			</mx:ArrayCollection>
		</mx:dataProvider>
	</mx:List>
</mx:Application>

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

This movie requires Flash Player 11

Maintenant, vous pourriez vous demander pourquoi quand on travaille avec un item editor, on ne pourrait pas simplement utiliser un item renderer. Par exemple, il est possible de faire une liste de NumberStepper comme itemRenderer dans l'exemple précédent. L'utilisateur pourrait mettre à jour la valeur du NumericStepper utilisé comme itemRenderer. Cependant, le fait est qu'un itemRenderer fait simplement le rendu de la data. Ils ne créent pas de data binding avec le dataProvider. C'est pourquoi, changer la valeur d'un NumericStepper utilisé comme itemRenderer ne va pas affecter le data provider, alors que le data provider sera bien mis à jour si on l'utilise en tant qu' itemEditor.

Cependant, vous pouvez indiquer à un composant d'utiliser l'itemRenderer comme un itemEditor en fixant la propriété rendererIsEditor à true:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="srcview/index.html">
	<mx:List editable="true" width="200" labelField="rating"
		itemRenderer="mx.controls.NumericStepper" rendererIsEditor="true" editorDataField="value">
		<mx:dataProvider>
			<mx:ArrayCollection>
				<mx:Array>
					<mx:Object songId="0" title="Astronaut" artist="David Byrne" rating="0"/>
					<mx:Object songId="1" title="Rio" artist="Duran Duran" rating="2"/>
					<mx:Object songId="2" title="Enjoy The Silence" artist="Depeche Mode" rating="1"/>
					<mx:Object songId="3" title="Mesopotamia" artist="B-52s" inFavorites="true" rating="4"/>
				</mx:Array>
			</mx:ArrayCollection>
		</mx:dataProvider>
	</mx:List>
</mx:Application>

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

This movie requires Flash Player 11

Tous les composants que vous utilisez comme itemRenderer peuvent être utilisés comme itemEditor. Il faut seulement que le composant ait un getter/setter indiqué comme Bindable, et vous devez spécifier la valeur de editorDataField pour le composant utilisant l'itemEditor. Dans l'exemple suivant, le getter/setter est fait sur la propriété "data", c'est donc elle qu'il faut mettre en tant qu' editorDataField.

Voici la modification de l'exemple qui vous avez pu trouver dans l'article sur les itemRenderer en composants MXML:

Composant Rating.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
	<![CDATA[
	import mx.containers.Canvas;

	private var _data:Object;

	[Bindable]
	override public function set data(value:Object):void{
		// on conserve la valeur dans une variable private
		// pour pouvoir la renvoyer dans le get
		_data = value;
		draw();
	}

	override public function get data():Object{
		return _data;
	}

	public function onClick(event:MouseEvent):void{
		// on stocke la valeur du composant cliqué dans l'objet _data, à la propriété rating
		_data.rating = uint(event.currentTarget.name);
		// on met à jour le renderer
		draw();
	}

	private function draw():void{
		// on prend la valeur de rating de l'Object value corrsespondant à la ligne
		var rating:uint = uint(_data.rating);
		// on enlève les composants qui pourraient être la avant
		// dans la cas d'un refresh par exemple
		removeAllChildren();
		var canvas:Canvas;
		for (var i:uint = 0; i < 5 ; i++){
			canvas = new Canvas;
			// définition de la couleur du canvas
			canvas.setStyle("backgroundColor", i< rating ? 0xFF0000 : 0x0000FF);
			canvas.width = 10;
			canvas.height = 10;
			canvas.name = String (i + 1);
			canvas.addEventListener(MouseEvent.CLICK, onClick);
			addChild(canvas);
		}
	}
	]]>
	</mx:Script>
</mx:HBox>

Et voici l'application Flex qui utilise maintenant Rating comme itemEditor. Cliquez sur les carrés pour modifier la valeur du rating (qui sera aussi modifiée dans le data provider:

<?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="Artiste" dataField="artist"/>
				<mx:DataGridColumn headerText="Vote" dataField="rating"
								itemRenderer="Rating" rendererIsEditor="true"
								editorDataField="data"/>
			</mx:columns>
			<mx:dataProvider>
				<mx:ArrayCollection>
					<mx:Array>
						<mx:Object songId="0" title="Astronaut" artist="David Byrne" inFavorites="true" rating="5"/>
						<mx:Object songId="1" title="Rio" artist="Duran Duran" rating="3"/>
						<mx:Object songId="2" title="Enjoy The Silence" artist="Depeche Mode" rating="4"/>
						<mx:Object songId="3" title="Mesopotamia" artist="B-52s" inFavorites="true" rating="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 (3) Trackbacks (0)
  1. Merci, tu viens la de m'enlever une grosse épine du pied !!

    je m'explique :

    J'ai mon appli principale avec une list. Un item renderer de ma liste qui affiche une image et une case à cocher pour choisir la liste des article que je veux acheter...

    Avant ta superbe solution je devais dans mon itemrenderer faire appel à une fonction de mon application principale via mon itemrenderer qui elle, mettais à jour mon dataprovider (un arraycollection) en fonction de l'item sélectionné et la valeur passé en paramètre via ma case à coché cb.selected (le bordel quoi...)

    Je faisais ça car, comme tu la si bien fait remarqué, l'item renderer ne sert que pour afficher les éléments et ne met pas à jour le dataprovider si les informations sont modifiées.

    Merci bcps, comme d'habitude tes trouvailles sont très intéressantes car souvent applicable à des projet concret !!!

  2. Et je rajoute.

    Pour ne pas garder ça pour moi voici donc comment j'ai palié à mon pb avec ta solution :

    Actionscript:
    1. private var _data:Object;
    2.        
    3.         [Bindable]
    4.     override public function set data(value:Object):void{
    5.         _data = value;
    6.     }
    7.  
    8.     override public function get data():Object{
    9.         return _data;
    10.     }
    11.  
    12.    
    13.     private function change():void{
    14.         _data.visible = cb.selected;
    15.     }

    MXML:

    Voila ;)

  3. Bonjour et merci pour ce site, qui fait référence.

    Je viens de construire un dataGrid avec itemEditor composé d'un ComboBox. Or je butais sur un bug potentiel qui peut se produire si l'utilisateur édite le champ mais ne sélectionne aucun item de la ComboBox.
    La solution : gérer la mise à jour du dataGrid au sein de l'événement "itemEditEnd" :

    Actionscript:
    1. [Bindable]  internal var _data4Combo:ArrayCollection;
    2. [Bindable]  private  var _row    :int = 0;
    3. [Bindable]  private var _langues:ArrayCollection;
    4.  
    5. _row = (this._langues.length &lt;14 ) ? this._langues.length : 14;
    6.  
    7. private function processData(event:DataGridEvent):void {
    8.  
    9.     event.preventDefault();
    10.     var index:int = ComboEditor(DataGrid(event.target).itemEditorInstance).myCombo.selectedIndex;
    11.    
    12.     myGrid.editedItemRenderer.data.EVAL = (index == -1) ? myGrid.editedItemRenderer.data.EVAL : _data4Combo[index].EVAL;
    13.                
    14.     // Close the cell editor.
    15.         myGrid.destroyItemEditor();
    16.                
    17.         // Notify the list control to update its display.
    18.     myGrid.dataProvider.itemUpdated(event.itemRenderer.data);
    19.  
    20. }

    MXML:
    1. <mx:DataGrid
    2.  
    3.       id="myGrid" top="60" left="20"
    4.  
    5.       dataProvider="{_langues}"
    6.  
    7.       visible="{_row != 0}" includeInLayout="{_row != 0}" rowCount="{_row}"
    8.  
    9.       editable="true"
    10.  
    11.       selectable="false"
    12.  
    13.       itemEditEnd="processData(event);">
    14.  
    15.       <mx:columns>
    16.  
    17.             <mx:DataGridColumn id="langages" dataField="LANG" textAlign="right" editable="false"/>
    18.  
    19.             <mx:DataGridColumn id="level" dataField="EVAL" width="300" itemEditor="ComboEditor"                             labelFunction="levelLabelFunction"/>
    20.  
    21.       </mx:columns>
    22.  
    23. </mx:DataGrid>


Leave a comment

(required)

Aucun trackbacks pour l'instant