Trigger an itemEditEnd event within the itemEditor - apache-flex

This might be an easy one for you DataGrid experts out there. I following an example for adding rows to a DataGrid dynamically from within a row
http://www.switchonthecode.com/tutorials/adding-dynamic-rows-to-flex-datagrid
My tweak that I am trying to acoomlish, is to have a custom itemEditor that is a form with two TextInputs and an OK button. For the life of me I can't get that button to trigger the DataGrid's itemEditEnd event where I have some processing before I call destroyItemEditor. I tried dispatching the event myself directly but got a strange error in DataGrid's updateDisplayList saying editedItemPosition was null (editedItemPosition.rowIndex). Any ideas?

I figured out the "duh" answer. Basically, within the itemEditor get reference to the DataGrid using listData.owner and then set the DataGrid's editedItemPosition and selectedIndex. This way lets the component worry about cleaning up the itemEditor.
var grid:DataGrid = listData.owner as DataGrid;
grid.editedItemPosition = null;
grid.selectedIndex = -1;

itemEditEnd will be triggered when you click outside the item editor. If you are dispatching it yourself, you need to set the rowIndex property of the event to the appropriate value before dispatching.

Related

Adobe Flex reference another object

I have a flex 3 datagrid that is in a completely separate container from the object that I am trying to reference it from - i.e. the datagrid is in a vbox, and I am trying to set a property in the datagrid from a popup.
How do I access the datagrid from the popup?
I'd like to do something like:
myView.myDatagrid.resizableColumns = false;
Using cairngorm as a framework if that is of any help.
You'll have to explain your architecture better to get a specific answer. This answer may help as everything I said about running methods on another component, also applies to accessing properties.
One solution for you is to pass the DataGrid instance into the popup as an instance variable; then the PopUp will be able to change the DataGrid's properties easy.
When you add your popup, you need to listen for an event. Then your PopUp needs to dispatch an event that the parent can handle.
myPopup.addEventListener(SomeEvent.DISABLE_COLUMNS,disableResize);
and then in the parent component
public function disableResize(event:SomeEvent):void{
myDatagrid.resizableColumns = false;
}
This assumes a custom event called SomeEvent... you can actually just create a default Flash event and give it a name like
dispatchEvent(new Event("MyDisableResizeEvent"));
Assuming you've got a button in your popup:
<mx:Button click="{dispatchEvent(new Event('MyDisableResizeEvent'));}" label="Disable Resizing"/>

Flex 3: Datagrid as item editor gets 'itemEditEnd' prematurely

My application has a tree with a custom item renderer, which depending on the type of data at a leaf uses different components as editors. In one case I am trying to use a datagrid so that the user can choose a row that meets his needs (several columns need to be displayed), ie. similar in concept to a ComboBox.
To do this I have a function assigned to be the handler for 'itemEditBegin' (for the tree) in which I'm dynamically creating the datagrid, and then using the popup manager to display it as a (modal) popup. So far so good.
However, if you click anywhere (eg. scroll down button in the datagrid) the popup disappears because the itemEditEnd event is fired - why ?!
In another scenario, I have a DateField setup as the editor, and the user can click on the icon to bring up a DateChooser, scroll through the months, etc. I looked at the code behind this, and it is using a popup, seemingly in exactly the same way as my code !
Here is the 'itemEditBegin' code:
dataGrid = new DataGrid();
dataGrid.dataProvider = mddTable.dataCollection;
dataGrid.editable = false;
PopUpManager.addPopUp(dataGrid, this, true);
where 'this' is the component used by the tree renderer for a row. It is the tree component's 'itemEditEnd' handler that is being called as soon as anything inside the datagrid is clicked (eg. a row, scroll down button, column divider etc).
Any ideas anyone ?
Thanks,
Mike.
I guess I'd have to see code, or this working in practice to fully understand. It sounds like the individual DataGrid Columns are editable when you're using the DataGrid as an itemEditor. Is that correct?
When you focus out of an itemEditor in the DataGrid, it will fire the itemEditEnd event. Your tree must be reacting to this somehow. Try to stop the event propogation in your DataGrid class. Conceptually something like this:
<mx:DataGrid>
<mx:Script>
public function oItemEditEnd(event:DataGridEvent):void{
event.stopPropogation();
}
</mx:Script>
<mx:columns>
<mx:DataGridColumn itemEditEnd="onItemEditEnd(event)">
<mx:DataGridColumn itemEditEnd="onItemEditEnd(event)">
</mx:columns>
</mx:DataGrid>
If you do this, you're going to have to do something to figure out when the user is done editing and close the itemEditor manually.
More info on stopPropogation().. Also check out stopImmediatePropogation(). I'm not sure which one you'll need as it depends how your code is structured.
Eventually I found a solution that moreless fixes the problem. Simply adding in the line:
dataGrid.owner = this;
solved the premature itemEditEnd event problem. However, now I have the opposite problem, where the itemEditEnd event doesn't get fired until I click on another row of the tree !
I have an 'item clicked' listener on the datagrid which destroys the datagrid when one of the values is clicked, but just doing this doesn't cause the itemEditEnd event of the underlying tree row to fire. I read in the docs that the component losing focus causes it, so I dispatched my own 'FocusEvent.FOCUS_OUT' event - no good.
If I manually change the focus to the underlying tree, the itemEditEnd event does fire and all is good, but it seems a bit clunky to have to pass a reference of the tree to the tree renderer's row object !
Anyone have any better ideas ?
Thanks,
Mike

flex list with itemRenderer

I have a simple list bounded to an ArrayCollection and an itemRenderer
When I add a new item to the ArrayCollection, I get the event addedToStage: FINE
Trouble is when I remove an item from the ArrayCollection, I never events :
I tried:
remove, removed, removedFromStage and I need to stop a stream when the items is removed:
So HOW can I get an event when an ITEM is REMOVED ?
Thanks
Thing is item renderers are recycled. So when you remove the item from your collection, the item renderer is not destroyed, it's just given another data.
You can add an event listener on the dataChange event or override the set data function.
What are your tring to do exactly?
You should listen to the ArrayCollection events if you want to know if the ArrayCollection instance is changed. But I'm not sure what you are trying to accomplish. If you remove an item from the ArrayCollection then you should know that it is removed. Why or where do you need an event?

What the best way to coordinate loading initial values in syncronized Combo-Boxes & List Box

Environment: Flex/As3/Cairgorm/composite component.
I have two comboboxes and two datagrids such that the selection of combobox 1, inserts data into combobox two and the fist datagrid. The selection of combobox 2 inserts data into datagrid 2.
I have setup the change event so that the user selection on each of the combo boxes do the right thing. The problem is that on the initial load of the comboboxes, the change event does not fire and subsequent synchronization data loading does not happen.
Is there an event for getting the itemselected (1st item) after the combobox is initialized?
I found my own answer. Using the updateComplete event on each of the comboboxes did the trick.
[EDIT]
It turns out that updateComplete did not work as expected. What I really needed is the dataChange event. However, it appears that this event does not fire for comboboxes even though it is listed as a valid FlexEvent for this component.
I tried a number of other events (valueCommit, creationComplete, initialize) but all of these fire multiple times, overlap with change, and are not useful for this usecase.
In the end, I created a gludge of a chain of calls for the initialize path and change path.
If anyone else has a better way, I'd be very interested.

how to loop over a datagrids rows in flex

I have a DataGrid which contains a DataGridColumn with a textinput and DataGridColumn with a Button.
The DataGrid is bound to some XML which displays values in the text box.
When the button for a row is clicked I need to get the value out of the text box and save it into the relevant XML node.
My solution was just to pass the id of the row to the button click event then loop over the rows until I find the id then just grab the text box value. Simple.
However the only advice I can find on looping over the rows is via the underlying dataProvider, which is nonsense as the two aren't the same thing.
Is this even possible? or is there a better way?
NOTE I would prefer not re-writing the markup, unless I have to.
Thanks
You are probably using an itemRenderer for your DataGridColumn to show the textBox (aka, TextInput component). I suggest that you dispatch a custom event out of the TextInput itemRenderer when you have a TextInput.dataChange event (or some other TextInput.Event that suits when you are ready to save the value).
http://livedocs.adobe.com/flex/3/langref/mx/controls/TextInput.html
Please remember that you need to bubble this event handling outside of the itemRenderer (e.g., the DataGrid) -- itemRenderers don't handle events well.
Also, one reason that a button to save your TextInput value is not a good idea, is because they are both itemRenderers, and it is hard to communicate between itemRenderers -- it is hard because Adobe deems it unclean code.
http://www.adobe.com/devnet/flex/articles/itemrenderers_pt1.html
Also, this is another solution that changes the dataProvider for a ComboBox (in your case, it's a TextInput instead of ComboBox):
http://www.switchonthecode.com/tutorials/simple-datagrid-item-editor-in-flex
listData.rowIndex from the itemRenderer returns the current row index. You can read it from the click handler as:
private function clickHandler(event:MouseEvent):void
{
var listData:BaseListData = IDropInListItemRenderer(event.target).listData;
var clickedRowIndex:Number = listData.rowIndex;
}

Resources