Setting the value of a PopUpMenuButton programmatically? - actionscript-3

I need to set some initial values in several mx PopUpMenuButton components. Based on this Adobe info I am casting the component as a Menu and setting the selectedIndex – but it isn't working.
Any tips? The function gets called and it appears that the selectedIndex is set but the PopUpMenuButton still displays the first item in its data provider.
private function initFontSizeData():void {
Menu(fontSizePopUp.popUp).selectedIndex = 3; // 48 pt
trace("index", Menu(fontSizePopUp.popUp).selectedIndex);
}
<mx:PopUpMenuButton id="fontSizePopUp"
name="fontSizePopUp"
width="50" height="20"
labelField="label"
paddingLeft="-8"
itemClick="toolChangeHandler(event)"
open="canvasEnabled(false)"
close="canvasEnabled(true)"
chromeColor="#cccccc"
toolTip="Font Size"
styleName="toolPopUpStyle"
creationComplete="initFontSizeData()"
popUpStyleName="toolPopUpStyle">
<mx:dataProvider>
<fx:Array>
<fx:Object fontPointSize = "18" label="18 pt"/>
<fx:Object fontPointSize = "24" label="24 pt" />
<fx:Object fontPointSize = "36" label="36 pt" />
<fx:Object fontPointSize = "48" label="48 pt" />
<fx:Object fontPointSize = "60" label="60 pt" />
<fx:Object fontPointSize = "72" label="72 pt"/>
<fx:Object fontPointSize = "96" label="96 pt" />
</fx:Array>
</mx:dataProvider>
</mx:PopUpMenuButton>

For some reason that I ignore (maybe it's just a bug), the label of the PopUpMenuButton control is not updated and that's why you have to force it to do that using one of these methods :
Using mx.core.mx_internal to commit the selected index :
Menu(fontSizePopUp.popUp).selectedIndex = 3;
Menu(fontSizePopUp.popUp).mx_internal::commitSelectedIndex(3);
Dispatching an mx.events.MenuEvent event :
var menu_event:MenuEvent = new MenuEvent(MenuEvent.ITEM_CLICK);
menu_event.index = 3;
Menu(fontSizePopUp.popUp).dispatchEvent(menu_event);
Dispatching an mx.events.FlexEvent event :
Menu(fontSizePopUp.popUp).selectedIndex = 3;
Menu(fontSizePopUp.popUp).dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
Hope that can help.

Related

Disable unselected items in a List After 5 items are selected

Im new to flex development. I have a dynamically data bound list component. I need to restrict user from selecting more than 5 items.
List is made with checkboxes and labels
getSelectionCount() method returns the number of currently selected items.
Here is my code
<s:VGroup width="100%" height="100%">
<s:List id="chkLst" visible="{isMultipleSelectionAllowed}" width="100%" height="100%" borderVisible="false"
fontFamily="segoeui"
dataProvider="{filteredDataSet}" >
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
//-----------------------------------------------
//
// Checkbox select
//
//-----------------------------------------------
protected function chk_clickHandler(event:MouseEvent):void
{
var selection:Array = new Array();
for each(var item:Object in outerDocument.chkLst.dataProvider)
{
selection.push(item);
}
var count:int = 0;
for each(var sItem:Object in selection)
{
outerDocument.setSelectionCount(0);
if(sItem.selected)
{
count++;
}
outerDocument.setSelectionCount(count);
}
Alert.show(outerDocument.getSelectionCount()+"","test");
if(CheckBox(event.target).selected && outerDocument.getSelectionCount() <= 5){
outerDocument.setSelectionCount(outerDocument.getSelectionCount()+1);
}
if(outerDocument.getSelectionCount() >= 6){
}
}
]]>
</fx:Script>
<s:HGroup width="100%" height="30" gap="2" paddingLeft="5" paddingRight="5" verticalAlign="middle" clipAndEnableScrolling="true">
<s:CheckBox id="chk"
label="{data.label}" change="{data.selected = chk.selected}" selected="{data.selected}"
maxWidth="215" click="chk_clickHandler(event)" />
</s:HGroup>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>
How can disable the checkboxes which user has not selected when user selection count exceeds 5 ?
2 I also need to enable all check boxes back if user unticks some checks in order that selection count go below 5
Thank You
First you need to add enabled property in your arraycollection like below which also make bindable in itemRenderer enabled="{data.enabled}". If count reach 5 we disable all button except selected one which the help of enabled property and magic here we need to update arraycollection items by using mx.collections.IList.itemUpdated(item:Object, property:Object=null, oldValue:Object=null, newValue:Object=null):void method so that only it will reflect disable the other checkboxes. In our case use outerDocument.chkLst.dataProvider.itemUpdated(item);
Sample arraycollection structure:
<fx:Declarations>
<s:ArrayCollection id="filteredDataSet" >
<fx:Object selected="false" enabled="true" label="one"/>
<fx:Object selected="true" enabled="true" label="two"/>
<fx:Object selected="false" enabled="true" label="three"/>
<fx:Object selected="false" enabled="true" label="four"/>
<fx:Object selected="false" enabled="true" label="five"/>
<fx:Object selected="false" enabled="true" label="six"/>
<fx:Object selected="false" enabled="true" label="seven"/>
<fx:Object selected="false" enabled="true" label="eight"/>
<fx:Object selected="false" enabled="true" label="nine"/>
</s:ArrayCollection>
</fx:Declarations>
<s:List id="chkLst" width="100%" height="100%" borderVisible="false"
fontFamily="segoeui"
dataProvider="{filteredDataSet}" >
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
protected function chk_clickHandler(event:MouseEvent):void
{
data.selected = chk.selected;
var selection:Array = [];
for each(var item:Object in outerDocument.chkLst.dataProvider)
{
if(item.selected)
selection.push(item);
}
if(selection.length>=5)
{
for each(var item:Object in outerDocument.chkLst.dataProvider){
item.enabled = item.selected;
outerDocument.chkLst.dataProvider.itemUpdated(item);
}
}else{
for each(var item:Object in outerDocument.chkLst.dataProvider){
item.enabled = true;
outerDocument.chkLst.dataProvider.itemUpdated(item);
}
}
}
]]>
</fx:Script>
<s:HGroup width="100%" height="30" gap="2" paddingLeft="5" paddingRight="5" verticalAlign="middle" clipAndEnableScrolling="true">
<s:CheckBox id="chk" label="{data.label}" selected="{data.selected}" enabled="{data.enabled}"
maxWidth="215" click="chk_clickHandler(event)" />
</s:HGroup>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>

Flex binding List selectedItem

I`m new with flex, and trying to combine data for 2 List selections, (SEE CODE BELOW):
<s:Label x="538" y="130" text="Industry of Interest:"/>
<s:List id="reIndustry" x="538" y="150" width="165" height="122" dataProvider="{recruitIndustries}" labelField="industry"></s:List>
<s:Label x="723" y="130" text="Qualifications:"/>
<s:List id="reQualifications" x="723" y="150" width="165" height="122" selectedItem="reIndustry.selectedItem.qualification" labelField="qualification"></s:List>
What i would like to accomplish is that when you select data from "reIndustry", more data of the selected item will then show in "reQualifications" List.
Here is my Data:
<s:ArrayList id="recruitIndustries">
<fx:Object industry="Admin/PA/Secretary" qualification="Other"/>
<fx:Object industry="Automotive" qualification="Painter"/>
<fx:Object industry="Building/Construct/Mine"/>
<fx:Object industry="Engineering"/>
<fx:Object industry="Finance/Accounting"/>
<fx:Object industry="FMCG"/>
<fx:Object industry="General Employment"/>
<fx:Object industry="Health and Skincare"/>
<fx:Object industry="Insurance"/>
<fx:Object industry="International"/>
<fx:Object industry="IT/Computer"/>
<fx:Object industry="Legal"/>
<fx:Object industry="Logistics"/>
<fx:Object industry="Management"/>
<fx:Object industry="Manufacturing"/>
<fx:Object industry="Medical"/>
<fx:Object industry="Part Time/ Temps"/>
<fx:Object industry="Professions"/>
<fx:Object industry="Retail"/>
<fx:Object industry="Sales and Marketing"/>
<fx:Object industry="Tourism/Hospitality"/>
</s:ArrayList>
If possible, how can I add more values for showing in the second List "reQualifications".
#RIAstar question is Correct.
You can do it by below code:-
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import spark.events.IndexChangeEvent;
[Bindable]
private var moreDataProvider:ArrayCollection = new ArrayCollection();
private function itemClickHandler(event:IndexChangeEvent):void
{
moreDataProvider.removeAll();
if(Object(reIndustry.selectedItem).hasOwnProperty('qualification'))
moreDataProvider.addItem(reIndustry.selectedItem);
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:Label x="538" y="130" text="Industry of Interest:"/>
<s:List id="reIndustry" dataProvider="{recruitIndustries}" x="538" y="150" width="165" height="122"
labelField="industry" change="itemClickHandler(event)"/>
<s:Label x="723" y="130" text="Qualifications:"/>
<s:List id="reQualifications" dataProvider="{moreDataProvider}" x="723" y="150" width="165" height="122"
labelField="qualification"/>

Selection highlighting in List doesn't disapear after intercepting value commit event

I am using a spark List and wanted to maintain the selection after changing the content of the list that is the data provider. If you set a new data provider the List sets its selectedIndex back to -1. We solved this problem by intercepting the valueCommit event that is fired when teh List wants to set itself back to -1 and setting the previously selected item (if the new data provider still contains it). This works so far but we are getting strange behaviour:
initially the previously selected item is still selected and highlighted as intended
if another item is selected, the highlighting stays on the intial item. It doesn't matter how often I select another one, the initial item is still highlighted but not selected. The newly selected item is in fact selected and also highlighted.
if the initial item is selected again the List is behaving normal again. When I select another item after I reselected the initial one once, the highlighting disapears.
The List is declared in an MXML like this:
<s:List dataProvider="{model.dataProvider}"
selectedIndex="#{model.selectedIndex}"
valueCommit="model.handleInputObjectListValueCommit(event)"/>
The code in the model class is very complex but this should be the relevant part:
[Bindable]
public var dataProvider:ArrayCollection;
[Bindable]
public var selectedIndex:int;
private var _indexToSelect:int = -1;
public function setNewContent(newContent:ArrayCollection):void {
undoManager.ignore(function ():void {
dataProvider.removeAll();
dataProvider.addAll(newContent);
_indexToSelect = selectedIndex;
});
}
public function handleValueCommit(event:Event):void {
if (_indexToSelect != -1) {
const localIndex:int = _indexToSelect;
_indexToSelect = -1;
selectedIndex = localIndex;
}
}
The undManager is a class that takes care of undo/redo. The ignore function takes care that the undoManager doesn't register the change in the dataProvider as an undoable action because only user interaction should be undoable.
any ideas?
I got the described result when capturing change events, and fixing it there would require either a hackish solution or a custom UI component to fix what seems like a bug in the List component. But it seems to work if you handle the logic as you change the data provider rather than trying to capture events:
public function setDataProvider(data:IList):void {
var previous:Object = theSparkList.selectedItem;
theSparkList.dataProvider = data;
var index:int = theSparkList.dataProvider.getItemIndex(previous);
if (index > -1) {
theSparkList.selectedIndex = index;
}
}
This might still require some refactoring, and it might not work with your architecture- you might have to provide more detail on that. Is capturing events the only choice?
Maybe when changing the dataProvider, re-instantiate the list control ...... list = new List();, or something along those lines to clear the settings for that control.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="_creationCompleteHandler()">
<s:layout>
<s:HorizontalLayout />
</s:layout>
<fx:Declarations>
<s:ArrayList id="d1">
<fx:Object label="Obj1" />
<fx:Object label="Obj2" />
<fx:Object label="Obj3" />
<fx:Object label="Obj4" />
<fx:Object label="Obj5" />
<fx:Object label="Obj6" />
<fx:Object label="Obj7" />
<fx:Object label="Obj8" />
<fx:Object label="Obj9" />
<fx:Object label="Obj10" />
<fx:Object label="Obj11" />
<fx:Object label="Obj12" />
<fx:Object label="Obj13" />
<fx:Object label="Obj14" />
</s:ArrayList>
<s:ArrayList id="d2">
<fx:Object label="AA1" />
<fx:Object label="AA2" />
<fx:Object label="AA3" />
<fx:Object label="AA4" />
<fx:Object label="AA5" />
<fx:Object label="AA6" />
<fx:Object label="AA7" />
<fx:Object label="AA8" />
<fx:Object label="AA9" />
</s:ArrayList>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.IList;
import mx.events.PropertyChangeEvent;
import spark.events.IndexChangeEvent;
[Bindable]
public var listDataProvider:IList;
private var _lastSelectedItemIndex:int = -1;
private function _creationCompleteHandler():void
{
list.addEventListener(IndexChangeEvent.CHANGE, _list_changeHandler);
addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, _propertyChangeHandler);
listDataProvider = d1;
}
private function changeButt_clickHandler():void
{
listDataProvider = d2;
}
private function _propertyChangeHandler(event:PropertyChangeEvent):void
{
list.selectedIndex = _lastSelectedItemIndex;
}
private function _list_changeHandler(event:IndexChangeEvent):void
{
_lastSelectedItemIndex = list.selectedIndex;
}
]]>
</fx:Script>
<s:List id="list"
dataProvider="{listDataProvider}"
height="200" />
<s:Button label="changeButt"
click="changeButt_clickHandler()" />
</s:Application>

Flex Spark datagrid

i have an error adding dataprovider on my spark datagrid:
Multiple initializers for property 'dataProvider'. (note: 'dataProvider' is the default property of 'spark.components.DataGrid').
My data is from s:httpService declaration and i put it in data grid something like this
<s:DataGrid includeIn="formState" x="348" y="57" width="287" dataProvider="{myHttpService}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="data1" headerText="Data Field 1"></s:GridColumn>
<s:GridColumn dataField="data2" headerText="Data Field 2"></s:GridColumn>
<s:GridColumn dataField="data3" headerText="Data Field 3"></s:GridColumn>
</s:ArrayList>
</s:columns>
<s:typicalItem>
<fx:Object dataField1="Sample Data" dataField2="Sample Data" dataField3="Sample Data"></fx:Object>
</s:typicalItem>
<s:ArrayList>
<fx:Object data1="data1" data2="data1" data3="data1"></fx:Object>
<fx:Object data1="data2" data2="data2" data3="data2"></fx:Object>
<fx:Object data1="data3" data2="data3" data3="data3"></fx:Object>
<fx:Object data1="data4" data2="data4" data3="data4"></fx:Object>
</s:ArrayList>
</s:DataGrid>
and my http service is:
<s:HTTPService id="myHttpService" url="http://host.com/mydata.php"/>
Your code specifies the dataProvider twice, inadvertently I think.
The first time it is specified as a property on the tag, on this line.
<s:DataGrid includeIn="formState" x="348" y="57" width="287" dataProvider="{myHttpService}">
The second time it is specified as a child of the DataGrid, with these blocks:
<s:ArrayList>
<fx:Object data1="data1" data2="data1" data3="data1"></fx:Object>
<fx:Object data1="data2" data2="data2" data3="data2"></fx:Object>
<fx:Object data1="data3" data2="data3" data3="data3"></fx:Object>
<fx:Object data1="data4" data2="data4" data3="data4"></fx:Object>
</s:ArrayList>
You can't specify the dataProvider in both cases.
Additionally, I'll add that your code, as is, is using myHttpService as the dataProvider (in thef irst line). You probably want to use the results of the myHttpService call as the dataProvider; not the actual myHttpService object.
I believe you could bind to myHttpService.lastResults if you wanted, by my preference is to have a formal results handler that deals with handling the results, Conceptually like this:
<s:HTTPService id="myHttpService" url="http://host.com/mydata.php" result="onMyResult(event)"/>
protected function onMyResult(event:ResultEvent):void{
this.myDataGrid.dataProvider = new ArrayCollection(event.results as Array);
}

Checkboxes in a DataGrid get selected after Scrolling down in actionscript 3

i have implemented code, where i put Checkboxes in a DataGrid. The problem is, when a checkbox is checked and i scroll down, other checkboxes are checked as well, without me having checked them. If i scroll up again, the checkbox, which i initially checked, isnt checked anymore. Can anybody help me please.
Here is the Code:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
initialize="main()" textAlign="right" textRotation="rotate270" title="HomeView">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
import mx.graphics.SolidColorStroke;
import spark.primitives.Rect;
import spark.skins.spark.DefaultComplexItemRenderer;
import spark.skins.spark.DefaultItemRenderer;
private var bL:ArrayList;
public function main():void{
hey.dataProvider=dataprovider;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<s:ArrayList id="dataprovider">
<fx:Object actName="myact1" actnumber="2" name="1"/>
<fx:Object actName="myact2" actnumber="55" name="2"/>
<fx:Object actName="myact1" actnumber="2" name="3"/>
<fx:Object actName="myact2" actnumber="55" name="4"/>
<fx:Object actName="myact1" actnumber="2"/>
<fx:Object actName="myact2" actnumber="55"/>
<fx:Object actName="myact1" actnumber="2"/>
<fx:Object actName="myact2" actnumber="55"/>
<fx:Object actName="myact1" actnumber="2" name="1"/>
<fx:Object actName="myact2" actnumber="55" name="2"/>
<fx:Object actName="myact1" actnumber="2" name="3"/>
<fx:Object actName="myact2" actnumber="55" name="4"/>
<fx:Object actName="myact1" actnumber="2"/>
<fx:Object actName="myact2" actnumber="55"/>
<fx:Object actName="myact1" actnumber="2"/>
<fx:Object actName="myact2" actnumber="55"/>
<fx:Object actName="myact1" actnumber="2" name="1"/>
<fx:Object actName="myact2" actnumber="55" name="2"/>
<fx:Object actName="myact1" actnumber="2" name="3"/>
<fx:Object actName="myact2" actnumber="55" name="4"/>
<fx:Object actName="myact1" actnumber="2"/>
<fx:Object actName="myact2" actnumber="55"/>
<fx:Object actName="myact1" actnumber="2"/>
<fx:Object actName="myact2" actnumber="55"/>
</s:ArrayList>
</fx:Declarations>
<s:DataGrid id="hey" x="-2" y="-1" width="323" height="415">
<s:columns>
<s:ArrayList>
<s:GridColumn id="my" dataField="wierd">
</s:GridColumn>
<s:GridColumn id="hi" dataField="checkboxes">
<s:itemRenderer>
<fx:Component>
<s:GridItemRenderer>
<fx:Script>
<![CDATA[
protected function checkbox1_clickHandler(event:MouseEvent):void
{
trace("clicked");
}
]]>
</fx:Script>
<s:CheckBox click="checkbox1_clickHandler(event)">
</s:CheckBox>
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
</s:View>
Here is a way to fix this issue. ( a work around )
The reason for this has something to do with the way it is implemented inside the Datagrid.
Eg: When you create 50 rows inside the Datagrid. It does not create 50 different instances of the row.. ( in a scrolling scenario ) rather, as you scroll up or down the same rows are populated with the differing data..( giving you a seamless experience of scrolling and viewing them )
So the trick to solving this problem would be to study the sample found in this link
http://www.actionscript.org/forums/attachment.php3?attachmentid=38409&d=1335099663
You would have to analyse the code in the cell renderer class found in the sample. In your case you would have to modify the DefaultItemRenderer or the DefaultComplexItemRenderer which ever is used by the Datagrid column.