Without an app and some test data, it is hard to put this all together and debug through it. Some things to think about: -I would set the .owner before calling addPopUp. Focus will be taken away from the TextInput in addPopUp and if owner isn't set, the DG may not react properly. -The row is not updated when moving from column to column. You'll see the .reason=NEW_COLUMN. I've 'cheated' and re-set it to NEW_ROW just to force per-column updating. -I would not allow clicking outside the popup. You might need some sort of custom border that has alpha=0 and covers the rest of the app. -Popping up titlewindows when editing cells seems like it would be visually shocking. There are master/detail type UIs that might be easier to implement and more usable. -Generally, a column's editor should edit what is represented in the column. That's why it is rare to have multiple controls in an editor for a column unless the column renderer is large in which case the editable controls usually fit within or just outside the cell.
________________________________ From: [email protected] [mailto:[EMAIL PROTECTED] On Behalf Of mcaplan_labnet Sent: Tuesday, December 11, 2007 6:47 PM To: [email protected] 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>

