I have a TileList cp with 10 item.
How can i call a function in 4. item (for example) from outside, where i created a TileList cp?
Thanks
UPDATE:
Based on your comments, this should be even easier. You would just loop through each of the rows in your List's dataProvider and make whatever changes are necessary. At the end of the function just call the refresh function on the ArrayCollection. Using my example below:
public function myFunction(evt:Event):void
{
for each (var o:MyObject in myDataProvider)
{
o.someProperty = "Updated";
}
myArrayCollection.refresh();
}
After the ArrayCollection is updated, calling the refresh function should cause the List to refresh its item renderers as well.
ORIGINAL ANSWER:
It sounds like you want to call a function outside your ItemRenderer when a button or something is clicked in the ItemRenderer but still be able to access the data for the item that was clicked.
Assuming I've got this correct, you still wouldn't need to access the ItemRenderer itself. You can just do something like this (just a rough example):
<fx:Script>
<![CDATA[
public function myFunction(evt:Event):void
{
trace(MyObject(myList.selectedItem).someProperty.toString());
}
]]>
</fx:Script>
<mx:List id="myList" dataProvider="{myDataProvider}" >
<mx:itemRenderer>
<fx:Component>
<mx:CheckBox selectedField="IsSelected" change="outerDocument.myFunction(event);" />
</fx:Component>
</mx:itemRenderer>
</mx:List>
If you do need to pass a completely separate parameter that's not stored in your List's dataProvider, just pass it as an argument to the change eventHandler.
change="outerDocument.myFunction(event, someOtherValue);"
Related
I am creating an opensource application for managing environmental resources in my county.
I have a problem on a dataprovider for an itemrenderer (combobox) i am using on a datagrid.
The application works, but I get a warning saying the itemrenderer dataprovider will not be reassigned data on its update with a setter. Even if I do not need to reassign the combobox itemrenderer dataprovider, for a matter of best practice I would like to solve this warning.
This is the usual code I use for getting dataprovider data as an array collection populated from the result of a web service in the parentDocument of the itemrenderer:
//set farmers arrayCollection values for combobox itemrenderer
[Bindable]
private var _acFarmers:ArrayCollection=new ArrayCollection;
public function set acFarmers(acFarmers:ArrayCollection):void{
_acFarmers=acFarmers;
}
//get machines ArrayCollection values
public function get acFarmers():ArrayCollection{
return _acFarmers;
}
This is the code for the datagrid itemrenderer (showing only the interested column of the datagrid):
<mx:DataGridColumn headerText="Agricoltore" dataField="farmerId" width="200" rendererIsEditor="true" editable="false">
<mx:itemRenderer>
<fx:Component id="cmpCmbFarmers">
<mx:HBox>
<s:ComboBox width="200"
id="cmbFarmers"
dataProvider="{outerDocument.acFarmers}"
labelField="companyName"
change="onSelectionChange(event)"
>
<fx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.events.ListEvent;
private var _ownerData:Object;
private function setSelected():void {
}
override public function set data(value:Object):void{
if(value != null) {
super.data=value;
_ownerData=value;
if(value.collectingMachineId!==null){
for each(var dp:Object in cmbFarmers.dataProvider){
var dpFarmerId:String=dp.farmerId
var dataFarmerId:String=value.farmerId;
if(dpFarmerId==dataFarmerId){
cmbFarmers.selectedItem=dp;
}
}
} else {
cmbFarmers.selectedIndex=0;
data.farmerId=cmbFarmers.selectedItem.farmerId;
}
}
}
import spark.events.IndexChangeEvent;
protected function onSelectionChange(event:IndexChangeEvent):void
{
data.farmerId=cmbFarmers.selectedItem.farmerId;
}
]]>
</fx:Script>
</s:ComboBox>
</mx:HBox>
</fx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
This code works if I call the itemrenderer service to get combobox data BEFORE calling the datagrid data service and setting the datagrid arraycollection at re response of the service.
BUT a warning is displayed because the combobox dataprovider will not get changes after a set function on its dataprovider (_acFarmers).
This is the only warning I have on an entire project but i did not manage how to solve it.
I would really appreciate any help.
Thanks
Paolo
You have to put [Bindable] metatag above your setter instead of above _acFarmers. Because right now your acFarmers property is not the source for data binding.
Or better use just public variable instead of getter and setter since you didn't implement other actions in them.
Link about databinding
Try to use dataChangeEvent
you can use the dataChange event with an item renderer or item editor. Flex dispatches the dataChange event every time the data property changes.
<mx:ItemRenderer dataChange="someFunction()">
or
dataToDisplay.addEventListener( FlexEvent.DATA_CHANGE, dataChange );
I have a Spark List with a data provider consisting of a list of filled out form applications. What is the best way to add a button to each List Item (form application)? This button will be named Open and will navigate to the specified form application.
Thanks in advance for any advice!
This is similar to what #www.Flextras.com said, so I'm not going to repeat that. However, I'll add an example and one or two things.
Your custom ItemRenderer might look like this:
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.events.ItemClickEvent;
private function requestForm():void {
var event:ItemClickEvent = new ItemClickEvent(ItemClickEvent.ITEM_CLICK);
event.index = itemIndex;
event.item = data;
owner.dispatchEvent(event);
}
]]>
</fx:Script>
<s:Label id="labelDisplay" verticalCenter="0" />
<s:Button right="0" label="open" verticalCenter="0" click="requestForm()" />
</s:ItemRenderer>
Two things that differ from Flextras' answer:
I use the built-in ItemClickEvent instead of a custom event > less
coding
I dispatch the event on the owner of the ItemRenderer, which
is in fact the List that contains this ItemRenderer. Because of this,
you don't need to bubble the Event.
Now to open the form when the Button is clicked, do something like this:
myList.addEventListener(ItemClickEvent.ITEM_CLICK, openForm);
private function openForm(event:ItemClickEvent):void {
trace("open " + event.item.toString());
}
Use a custom itemRenderer which displays the button along w/ your itemRenderer data (form application).
When the button is clicked; dispatch a custom event which bubbles. You may have to include some identifier for the form application this button click represents.
Listen to the event on the list class using the addEventListener() method. You can't use MXML since you'll be using a custom event undefined in the List's default metadata.
In your listener, perform the relevant UI changes to display your form application.
As I am somewhat new to Flex I may be missing something fundamental here. I have a Spark List container whose dataProvider is bound to a result set coming back from a RemoteObject call. Pretty standard stuff.
<s:List id="list" dataProvider="{model.stuff}" width="100%" height="100%"
selectedIndex="#{selectedSlider.value}"
itemRenderer="{stuffRenderer}">
</s:List>
The selectedIndex is associated with an HSlider, but that is not the problem. My issue is that I would like to automatically select a certain "preferred" element from the list (only initially...to guide the user).
I tried to do that in a creationComplete event but my data hadn't shown up yet...setting selectedIndex didn't work...it was too early.
What's the right way to do this?
private function findAllUsers_resultHandler(e:ResultEvent):void
{
list.dataProvider = new ArrayCollection(e.result as Array);
if(firstTry)
{
list.selectedIndex = 0;
firstTry = false;
}
}
spark.components.List has spark.components.SkinnableDataContainer in its class hierarchy which dispatches a dataProviderChanged event whenever the dataProvider changes. Unfortunatly there is no [Event] metadata in SkinnableDataContainer that allows using this event in MXML. So, you'll need to create your own custom component that extends List.
package
{
import spark.components.List;
[Event(name="dataProviderChanged", type="flash.events.Event")]
public class MyList extends List
{
public function MyList()
{
super();
}
}
}
By using your custom component you can add an event listener for dataProviderChanged and update your selectedIndex accordingly.
<ns1:MyList id="list" dataProvider="{model.stuff}" width="100%" height="100%"
dataProviderChanged="selectedIndex = selectedSlider.value"
selectedIndex="#{selectedSlider.value}"
itemRenderer="{stuffRenderer}">
</ns1:MyList>
BTW: This works with other List-based components (like DropDownList) too.
I believe it should work if you just set the initial value of the slider to the index you want to be selected at the beginning.
Something like this:
<s:List dataProvider="{yourData}" selectedIndex="{hSlider.value}" /> <s:HSlider id="hSlider" minimum="0" maximum="{yourData.length - 1}" stepSize="1" value="theIndexYouWantAsInitial" liveDragging="true" />
That should work.
HTH
FTQuest
I'm trying to setup a DataGrid that contains a column of combo boxes. The values of the combo boxes are defined by data specific to that row. I cannot get this to work though, I'm asking for a solution to this, either fixing what I have below or a recommendation on a different way.
One of the columns of my DataGrid has an object derived from a ComboBox for an ItemEditor. The itemEditor is set like this:
<mx:DataGridColumn editorDataField="selectedItem" dataField="type" editable="true" >
<mx:itemEditor>
<mx:Component>
<FilterCell:SelectCellBase initialize="set_combo()" grid="{this}"/>
</mx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
So that when the itemEditor is generated (when the user double clicks on the cell) the data is populated.
Then, the SelectCellBase set_combo() function is defined as such:
public function set_combo( ) : void
{
var type : String = grid.dataProvider[grid.selectedIndex]['type'];
if( 'text' == type )
{
this.dataProvider = text;
}
else
{
this.dataProvider = number;
}
}
This implementation isn't working though because when I try to call grid.selectedIndex this always seems to return -1.
What am I doing wrong, or what better way is there to do this?
Your problem is that when you're inside of an <mx:Component> the scope is local, and no longer set to the outside MXML file. So when you have:
<mx:Component>
<FilterCell:SelectCellBase initialize="set_combo()" grid="{this}"/>
</mx:Component>
the "this" you're referring to is the inline component you've defined, not the base MXML component you're working on. The easy fix is to change it to
<mx:Component>
<FilterCell:SelectCellBase initialize="set_combo()" grid="{outerDocument}"/>
</mx:Component>
the outerDocument variable is automatically set when you're inside of an <mx:Component> tag, and can be used to access anything needed from the parent scope.
I have a ToggleButtonBar with a DataProvider setup like this:
<mx:ToggleButtonBar itemClick="clickHandler(event);" selectedIndex="0">
<mx:dataProvider>
<mx:String>{resourceManager.getString('dashboard','daily')}</mx:String>
<mx:String>{resourceManager.getString('dashboard','monthly')}</mx:String>
<mx:String>{resourceManager.getString('dashboard','quarterly')}</mx:String>
<mx:String>{resourceManager.getString('dashboard','yearly')}</mx:String>
</mx:dataProvider>
</mx:ToggleButtonBar>
To switch locale to Chinese, I have a combobox with this handler:
resourceManager.localeChain = "zh_CN";
My problem is that on locale change, while the labels for all the other controls on the screen dynamically reload for the new locale, the dataProvider values don't refresh.
I can manually reset them in code, but is there a cleaner solution?
I would abstract out the data for your data provider into a bindable variable, then just reset the data provider when you change locals.
<mx:Script>
<![CDATA[
[Bindable]
myArray:Array = new Array(
[resourceManager.getString('dashboard','daily')]
, [resourceManager.getString('dashboard','monthly')]
, [{resourceManager.getString('dashboard','quarterly')]
, [resourceManager.getString('dashboard','yearly')]);
]]>
</mx:Script>
<mx:ToggleButtonBar itemClick="clickHandler(event);"
selectedIndex="0" id="myToggleButtonBar" dataprovider="{myArray}" />
Then you can just say
myToggleButtonBar.dataProvider = myArray;
after you swap the locals and it should work.
Disclaimer, there may be some minor errors in my code, I obviously am not able to test it and I don't have flex builder available right now to even check my syntax so I hope I didn't make any spelling mistakes. But this should get you in the ballpark.
Maybe if you make a getter bindable to a custom event for ex: "langChange"
[Bindable("langChange")]
public function get dataProviderToggleB():ArrayCollection
{
var arr :ArrayCollection = new ArrayCollection();
arr.addItem(resourceManager.getString('dashboard','daily'));
arr.addItem(resourceManager.getString('dashboard','monthly'));
return arr;
}
and in your "resourceManager.localeChain" setter you dispatch:
dispatchEvent(new Event("langChange"));
and you can used like this:
<mx:ToggleButtonBar dataProvider="{dataProviderToggleB} itemClick="clickHandler(event);" selectedIndex="0">
I hope this would help you.
You should keep 'daily', ... in your array and use a labelFunction to translate the label.
When the resourceManager sends a change event you should do a combo.labelFunction = labelFunction
The trick is to add brackets around each element in the dataProvider array, that way it gets parsed correctly. Note that this also binds correctly to locale changes in flex, no custom event dispatching is needed.
<mx:ToggleButtonBar itemClick="clickHandler(event);" selectedIndex="0"
dataProvider="{[ (resourceManager.getString('dashboard','daily')),
(resourceManager.getString('dashboard','monthly')),
(resourceManager.getString('dashboard','quarterly')),
(resourceManager.getString('dashboard','yearly')) ]}">
</mx:ToggleButtonBar>