Check out my blog entry I just posted on this topic (I already had the code sample lying around and hadn't gotten around to posting it),
http://blog.739saintlouis.com/2007/12/12/datagrid-popup-as-itemeditor/ HTH -Kyle ________________________________ From: flexcoders@yahoogroups.com [mailto:[EMAIL PROTECTED] On Behalf Of Alex Harui Sent: Tuesday, December 11, 2007 9:37 PM To: flexcoders@yahoogroups.com Subject: RE: [flexcoders] Re: Use a Popup as itemEditor in Datagrids I might have time to look at this over the weekend. ________________________________ From: flexcoders@yahoogroups.com [mailto:[EMAIL PROTECTED] On Behalf Of mcaplan_labnet Sent: Tuesday, December 11, 2007 6:47 PM To: flexcoders@yahoogroups.com Subject: [flexcoders] Re: Use a Popup as itemEditor in Datagrids I seem to keep on banging my head against a wall on this issue. I've been plugging away at this issue for several days now with little progress. I set the popup.owner property as recommended by Alex. This seemed to have helped, but issues still persist. I "cheated" and created an inPopup flag in the parent document to try and thwart popup loops (see code snips below). I say cheated, because I gathered from Alex's suggestion that I should not need to do that. Regardless, that hack worked marginally well, but I'm having additional issue, and I know it is because I am just not getting it. My hunch is that these additional issues are side effects to my improper implementation of the popup in the itemEditor. These "side effect" issues I am seeing include: - My itemRenderer is not being reliably updated. To be clear, the data from the itemEditor is being properly trapped, and the dataProvider updated. The itemRender is not being updated because it appears that the dataChange event on the itemRenderer is not being dispatched -- at least not reliably. It is being dispatched and the itemRenderer updated when I edit a different column in the datagrid. - If I click outside of my modal popup, focus is lost on the current itemEditor cell resulting in the first row itemEditor being executed immediately following the close of my initial popup. I've _covered_ my popup with focusEnabled = false statements which work great in the popup. But outside popup clicks messes the focus. For my first flex project, I've bitten off much more than I can chew here. :) I've gone through the Flex 3 docs, flexcoders, and google end-to-end, and I'm just not seeing a solution. Any kind gurus out there that can offer some guidance? I've included code snippets for all the components below. Thanks! Mike <?xml version="1.0" encoding="utf-8"?> <!-- modules.Case --> <comp:ModuleTitleWindow xmlns:mx="http://www.adobe.com/2006/mxml <http://www.adobe.com/2006/mxml> " layout="absolute" xmlns:comp="components.*" initialize="init();" verticalScrollPolicy="off" horizontalScrollPolicy="off" title="Case {caseNumber}" showCloseButton="true" close="closePopUp();" borderAlpha="1" width="100%" height="100%" implements="modules.Case.ICase"> <mx:Script> <![CDATA[ import mx.events.DataGridEventReason; import mx.events.DataGridEvent; /** * Flag for modules.Case.TeethEditor to ensure there is no popup loop */ public var inPopup:Boolean = false; /** * procedures datagrid itemEditEnd event handler */ private function procedureUpdate(event:DataGridEvent):void { if (event.reason == DataGridEventReason.CANCELLED) { return; } switch (event.dataField) { case "macro_id" : // Disable copying data back to the control. event.preventDefault(); // Get new city from editor. procedures.selectedItem.description = MacroIdEditor(DataGrid(event.target).itemEditorInstance).selectedItem.de scription; // Close the cell editor. procedures.destroyItemEditor(); // Notify the list control to update its display. procedures.dataProvider.itemUpdated(event.itemRenderer.data); break; case "teeth" : // Disable copying data back to the control. event.preventDefault(); if (!inPopup) { // Check to see that the popup is not active // Get new city from editor. procedures.selectedItem.teeth = TeethEditor(DataGrid(event.target).itemEditorInstance).teeth; // Notify the list control to update its display. procedures.dataProvider.itemUpdated(event.itemRenderer.data); // Close the cell editor. procedures.destroyItemEditor(); } break; } } ]]> </mx:Script> <mx:DataGrid id="procedures" editable="true" itemEditEnd="procedureUpdate(event);"> <mx:dataProvider> <mx:ArrayCollection> <mx:source> <mx:Object macro_id="D2456" teeth="11" /> <mx:Object macro_id="D2445" teeth="12,13" /> <mx:Object macro_id="D2658" teeth="21,22" /> </mx:source> </mx:ArrayCollection> </mx:dataProvider> <mx:columns> <mx:DataGridColumn dataField="macro_id" editable="true" itemEditor="modules.Case.MacroIdEditor" /> <mx:DataGridColumn dataField="teeth" editable="true" itemEditor="modules.Case.TeethEditor" editorDataField="teeth" itemRenderer="modules.Case.TeethRenderer" /> </mx:columns> </mx:DataGrid> </comp:ModuleTitleWindow> <?xml version="1.0" encoding="utf-8"?> <!-- modules.Case.TeethEditor --> <mx:TextInput xmlns:mx="http://www.adobe.com/2006/mxml <http://www.adobe.com/2006/mxml> " creationComplete="_init()" text="{_converted}" editable="false"> <mx:Script> <![CDATA[ import modules.Case; import mx.managers.PopUpManager; import modules.Case.TeethSelector; import mx.events.FlexEvent; import mx.utils.StringUtil; /** * Teeth selected */ [Bindable] public function get teeth():String { return _teeth; } public function set teeth(value:String):void { _teeth = value; data.teeth = _teeth; } private var _teeth:String; /** * text to display in textarea * @ private */ [Bindable] private var _converted:String; /** * Tooth selector popup instance */ private var _popup:TeethSelector; /** * Reference to the parent document which contains the datagrid */ private var _c:Case; /** * creationComplete event handler */ private function _init():void { teeth = data.teeth; addEventListener(FlexEvent.DATA_CHANGE, _dataChanged); _updateText(data.teeth); _c = parentDocument as Case; // Only show the popup teeth selector // if the popup isn't already displayed if (!_c.inPopup) { _c.inPopup = true; _popTeethSelector(); } } /** * Display popup teeth selector */ private function _popTeethSelector():void { _popup = new TeethSelector(); _popup.teeth = teeth; // handle popup updated event _popup.addEventListener("updated", _updateTeeth); // handle popup closing event _popup.addEventListener("closing", _closePopup); _popup.focusEnabled = false; PopUpManager.addPopUp(_popup, _c.procedures.editedItemRenderer as DisplayObject, true); // popup owner is the current datagrid item renderer _popup.owner = _c.procedures.editedItemRenderer as DisplayObjectContainer; PopUpManager.centerPopUp(_popup); } /** * Handle the updated event of the popup teeth * selector by grabbing the newly selected teeth and * and removing the popup */ private function _updateTeeth(e:Event):void { teeth = _popup.teeth; _c.inPopup = false; _updateText(teeth); PopUpManager.removePopUp(_popup); } /** * Handle the closing event of the poup teeth * selector by closing the popup */ private function _closePopup(e:Event):void { _c.inPopup = false; PopUpManager.removePopUp(_popup); } /** * Update the displayed textarea text */ private function _updateText(teeth:String):void { // updates _converted ... } /** * dataChanged event handler - this updates the displayed * textarea text */ private function _dataChanged(e:Event):void { teeth = data.teeth; _updateText(data.teeth); } ]]> </mx:Script> </mx:TextInput> <?xml version="1.0" encoding="utf-8"?> <!-- modules.Case.TeethSelector --> <mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml <http://www.adobe.com/2006/mxml> " title="Tooth Selector" creationComplete="_init()" showCloseButton="true" close="this.dispatchEvent( new Event('closing') );" focusEnabled="false"> <mx:Metadata> [Event("updated")] </mx:Metadata> <mx:Metadata> [Event("closing")] </mx:Metadata> <mx:Script> <![CDATA[ import mx.managers.PopUpManager; import mx.controls.CheckBox; import mx.utils.StringUtil; public var teeth:String; /** * creationComplete event handler */ private function _init():void { // set selected teeth } /** * Save function. Updates the teeth variable * and dispatches the updated event */ private function _done():void { teeth = // .... this.dispatchEvent( new Event("updated") ); } ]]> </mx:Script> <mx:Canvas> <mx:CheckBox x="28.2" y="111" id="t28" styleName="t28" focusEnabled="false"/> <mx:CheckBox x="152.2" y="141.3" id="t48" styleName="t48" focusEnabled="false"/> <!-- ... --> </mx:Canvas> </mx:TitleWindow> <?xml version="1.0" encoding="utf-8"?> <!-- modules.Case.TeethRenderer --> <mx:Label xmlns:mx="http://www.adobe.com/2006/mxml <http://www.adobe.com/2006/mxml> " width="100%" creationComplete="_init()" text="{_converted}"> <mx:Script> <![CDATA[ import mx.utils.StringUtil; import mx.events.FlexEvent; /** * label text */ [Bindable] private var _converted:String; /** * creationComplete event handler */ private function _init():void { _updateText(); addEventListener(FlexEvent.DATA_CHANGE, _dataChanged); } /** * update label displayed text */ private function _updateText():void { // update _converted var here ... } /** * dataChanged event handler. Updates the label text */ private function _dataChanged(e:Event):void { _updateText(); } ]]> </mx:Script> </mx:Label>