Spark List: ensureIndexIsVisible with expanding list itemRenderer - actionscript-3

I have a Spark List with an expanding itemRenderer (snippet of it below). It works very well but I am struggling to display the fully expanded list item when calling ensureIndexIsVisible. I've tried various things with validate/invalidate to try to force the List to take the expanded item size into account but either I am doing it wrong or the List component isn't built to handle this.
In the image below, I've called myList.ensureIndexIsVisible(7);Item 7 is expanded and the header scrolled to be visible but most of the expanded item is offscreen.
Anyone know a way to address this?
Update: If the List is specified to have useVirtualLayout="false" then the following works:
myList.validateNow();
myList.ensureIndexIsVisible(expandIndex);
but of course if there are a lot of cells in the List instance then this is a problem.
protected function expandOne_clickHandler(event:MouseEvent):void
{
var expandIndex:Number = Number(expandTarget.text);
data.getItemAt(expandIndex).selected = true;
myList.invalidateDisplayList();
myList.ensureIndexIsVisible(expandIndex);
myList.validateNow();
}
List itemRenderer:
<s:CheckBox id="eventName"
label="{data.eventName}"
top="0" left="0" right="0" bottom="0"
skinClass="skins.SatelliteEventSkin"
selected="{data.selected}"
click="{data.selected = !data.selected}"/>
<s:VGroup includeInLayout="{eventName.selected}"
visible="{eventName.selected}"
top="30" left="10" right="10" bottom="10">
<s:HGroup verticalAlign="middle" width="100%" >
<s:Spacer width="100%"/>
<s:Label text="eventID"/>
<s:Label id="eventID"
width="150"
text="{data.eventID}"/>
</s:HGroup>
etc...

Try to set selectedIndex value or just scroll your List using verticalScrollPosition value -myList.layout.verticalScrollPosition += your_item_height;.

Related

Actionscript 3 setStyle is not a function

I am trying to style a Flex 4 GridItem using actionscript, I have tried the following:
<mx:VBox
height="878" width="1920"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:local="*" creationComplete="addStyles()">
<mx:Script>
<![CDATA[
public var selectedLot:String = "";
private function addStyles():void
{
testBorder.setStyle("borderThickness", "3");
}
but I get the following error:
setStyle is not a function.
Am I missing something?
The GridItem is inside a repeater.
Here is my GridItem:
<mx:GridItem id="testBorder" width="101" height="52.25" horizontalAlign="center" verticalAlign="middle" borderStyle="solid" borderColor="gray">
<mx:Image source="assets/ruler-icon.png" />
<s:Label text="{r.currentItem.sqft}" fontSize="10" color="#808080" fontFamily="Helvetica" />
</mx:GridItem>
When using a repeater the GridItem's id will not be the same. To access any item inside a repeater you have to specify an index which is correspondent to the repeated item.
Example: Array consists of ["Audi", "BMW"], we set this array to your repeater's dataProvider, then to access "Audi"'s grid item and set its style, we have to use:
testBorder[0].setStyle("borderThickness", "3");
Additionally, an important point to consider, the VBox "creationComplete" can be executed before the repeater is fully built, therefore, the best place to call your function "addStyles" is in the repeater's "repeatEnd" event i.e (repeatEnd="setTransactionPropertyType()").
Hope this helps,
Goodluck.

Items in DataGrid not initialized as expected

I seem to have a problem of items not being created as expected, resulting in event-listeners not being fired.
I am using a DataGrid column of checkboxes as seen here:
<mx:DataGrid id="gridComponents" height="100%">
<mx:columns>
<fwctrl:DataGridCheckBoxColumn id="colChkBox" width="20" selectionChanged="onGridChbBoxChange(event)" />
<mx:DataGridColumn headerText="Components" dataField="name" width="250"/>
</mx:columns>
</mx:DataGrid>
(fwctrl is the namespace of an internal library.)
And here is what the mxml of fwctrl:DataGridCheckBoxColumn looks like:
<mx:DataGridColumn xmlns:mx="http://www.adobe.com/2006/mxml" resizable="false" xmlns:grid="fwctrl.grid.*" xmlns:CheckBoxColumn="fwctrl.grid.CheckBoxColumn.*">
<mx:Metadata>
[Event(name="selectionChanged", type="fwctrl.grid.CheckBoxColumn.DataColumnCheckBoxEvent")]
</mx:Metadata>
<mx:Script>
<![CDATA[
...
]]>
</mx:Script>
<mx:headerRenderer>
<mx:Component>
<CheckBoxColumn:CheckBoxHeaderRenderer textAlign="center" click="checkboxheaderrenderer1_clickHandler(event)">
<mx:Script>
...
</mx:Script>
</CheckBoxColumn:CheckBoxHeaderRenderer>
</mx:Component>
</mx:headerRenderer>
<mx:itemRenderer>
<mx:Component>
<mx:Box horizontalAlign="center"
verticalAlign="middle" enabled="{outerDocument.isEnabled}">
<mx:Script>
<![CDATA[
...
protected function checkBox_initializeHandler(event:FlexEvent):void
{
trace("init checkbox");
}
]]>
</mx:Script>
<mx:CheckBox id="checkBox" click="onCheckBoxClick()" change="onChange(event)" initialize="checkBox_initializeHandler(event)"/>
</mx:Box>
</mx:Component>
</mx:itemRenderer>
CheckBoxHeaderRenderer is a class that inherits from checkbox.
using the mxml above I bind an ArrayCollection to the data provide by doing: gridComponents.dataProvider = coll;
Having the checkBox_initializeHandler event bound, I expect to see a message printed for each element in my collection.
In reality, the message will only be displayed for element that don't "fall off the grid", i.e. if there is a scroll bar (due to a lot of items being rendered), the items that are below the bottom of the grid (i.e. the ones that need to be scrolled to) will not print a message.
This also means that they are not created correctly and that the click="onCheckBoxClick()" is not hooked correctly and that onCheckBoxClick() does not get triggered.
Why is this happening and how can I fix this?
In Flex, itemRenderers aren't created on a one-to-one basis with your underlying data collection. You only get enough instances to display one screen's worth of data, and those instances get reused as you scroll.
To handle this in your code, refactor so that your click handler in the itemRenderer updates a property in your dataCollection (e.g. data.foo = true;).

Strange behaviour of scrolling in flex mobile

working on flex mobile list. list is represented using itemrenderer.
here is the itemrendeerer..
<s:Image id="img" x="30" y="50"/>
<s:Label id="nameLbl" width="100%" height="100%" text="Label" textAlign="center" verticalAlign="middle"/>
<s:Button id="checkMarkLabel" label="+" height="100%" />
on selected::
protected function onClicked(event:MouseEvent):void
{
if(checkMarkLabel.label =="✓")
{
checkMarkLabel.label = "+";
}
else if(checkMarkLabel.label == "+" )
{
checkMarkLabel.label = "✓";
trace("id::"+event.currentTarget.data.id)
//FlexGlobals.topLevelApplication.selectedId = event.currentTarget.data.id;
}
}
the image gives you the clear picture.
after selecting some items in the list,if i scroll the list,the checked items gets unchecked and the unchecked items gets checked.any answer is appreciable..
Flex don't create renderer for each item in list instead Flex create few renderers (in your case 6) and reuse them.
You must save data about clicked list items (maybe use some singleton), and then you must override set data method in renderer class (in this method you get list item for renderer), then you figure out clicked this item or not and set to checkMarkLabel corresponded symbol.
On the list you can set the property "useVirtualLayout" to false. This will generate an unique itemrenderer for each item in the list. This is also what Anton was talking about.
This is however less resource friendly. If your list get's really large it will take up more memory.
You should work with states that are already made use of by lists in combination with itemrenderers.
Example itemrenderer:
<fx:Script>
<![CDATA[
protected function marker_clickHandler(event:MouseEvent):void {
marker.label = marker.label == "V" ? "+" : "V";
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="selected"/>
</s:states>
<s:Button label.selected="V" label.normal="+"/>
<s:Button y="10" id="marker" click="marker_clickHandler(event)" label="+"/>
If you were to use this as an itemrenderer, the button utilizing states will update as expected, but like Anton mentioned, the ones marked manually onClick will not get updated as expected.
This answer builds on Robin van den Bogaard's answer.
Assuming your current dataProvider has objects that look like this:
public class MyData {
[Bindable]
private var imgUrl:String;
[Bindable]
private var name:String;
}
Add a new field to it:
[Bindable]
private var chosen:Boolean;
(If you don't have [Bindable], add it to enable data binding on the data items.)
Then your itemRenderer can look like this, automatically updating as you scroll:
<fx:Script>
<![CDATA[
protected function marker_clickHandler(event:MouseEvent):void {
data.chosen = !data.chosen;
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="selected"/>
</s:states>
<s:Image id="img" x="30" y="50" source="{data.imgUrl}" />
<s:Label id="nameLbl" width="100%" height="100%" text="Label" textAlign="center" verticalAlign="middle" text="{data.name}" />
<s:Button id="checkMarkLabel" label="{data.chosen ? '✓' : '+'}" height="100%" click="marker_clickHandler(event)" />

Flex 4.x accordion items child unknown in actionscript

I have an Accordion component in Flex that has two children,
at the load of my page, I want to give the textvalue of a textfield in the first children to a textfield in the second children by using actionscript, but its faild
nb : when I click the secode children and I return to pass the textvalue from the first children, the action succeed!
<mx:HBox width="100%" height="310" horizontalAlign="center">
<mx:Accordion id="accordion1" width="100%" height="310" historyManagementEnabled="true">
<!-- child 1--><mx:VBox id="theme_resultat" width="95%" height="95%"
label="Résultat" horizontalAlign="center"
verticalAlign="middle">
<s:HGroup left="0" right="0" bottom="0" width="98%"
horizontalAlign="right">
<s:TextInput id="doc"/>
<mx:Button id="btnAdd" label="Add"
click="add_text(event)"
icon="#Embed('assets/images/add.png')"
paddingLeft="3" paddingRight="3"/>
</s:HGroup>
</mx:VBox>
<!-- child 2--><mx:VBox id="theme_detail" width="95%" height="95%" label="Détail"
verticalAlign="middle">
<mx:VBox width="100%" height="150" horizontalAlign="center">
<s:HGroup>
<mx:FormItem label="Titre:" paddingLeft="5">
<mx:TextInput id="doc_titre"/>
</mx:FormItem>
</s:HGroup>
</mx:VBox>
</mx:VBox>
</mx:Accordion>
</mx:HBox>
protected function add_text(event:MouseEvent):void
{
accordion1.selectedIndex=1;
doc_titre.text = doc.text;
}
}
when I click add I move to the second child, but the (mx:TextInput id="doc_titre") dont have the value of (s:TextInput id="doc"/)
for the second time I return to the child 1 and I click add, then I move to the second child and I find the value of (s:TextInput id="doc") in (mx:TextInput id="doc_titre")
What happens exactly? I think your problem may be caused by the fact that the components on the second children are not created until that view is opened, There are many solution for this, you could write some code in the creation complete oof the second view that will load the correct value, you can use databinding to bind the text inputs to the same string or you can try setting creationPolicy to all.
My answer is based on my above assumption so if I am wrong please give more details.
Check this http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7cb8.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ae5 and try setting the creationPolicy to all then let us know if the problem is solved
Use createDefferedContent() instead:
for (var i:int = 0; i < accordion.numChildren; i++)
{
(accordion.getElementAt(i) as NavigatorContent).createDeferredContent();
}
This method creates the children and their components in the background. Don't use creationPolicy as I did since this causes memory-related issues.

flex spark list Drag and drop an item on a spark canvas component

i have a spark list that displays a list of images that represent products. i am trying to implement a drag and drop functionality that allows the user to drag the products he wants to buy from the list to canvas area where he can see the products he choose before buying them. i am using the code below but i cannot figure out what is wrong with it , it seems that i am unable to use the list item as a draginitiator, can any one help please:
private function onMouseDown( event : MouseEvent ) : void
{
var list:List = List(event.currentTarget);
var dragInitiator:Image = Image (list.selectedItem);
var source : DragSource = new DragSource();
source.addData(dragInitiator, "img");
DragManager.doDrag(dragInitiator, source, event);
}
protected function canvas1_dragEnterHandler(event:DragEvent):void
{
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
protected function canvas1_dragDropHandler(event:DragEvent):void
{
Image(event.dragInitiator).x =
Canvas(event.currentTarget).mouseX;
Image(event.dragInitiator).y =
Canvas(event.currentTarget).mouseY; }
<fx:Model id="categoriesModel" source="Data/Categories.xml"/>
<s:ArrayList id="CategoriesCollection" source="{categoriesModel.Category}"/>
<fx:Model id="productsModel" source="Data/Products.xml"/>
<s:ArrayList id="ProductsCollection" source="{productsModel.Product}" />
</fx:Declarations>
<s:VGroup gap="5" horizontalAlign="center">
<s:HGroup gap="5">
<Components:PROExpressLogo/>
<s:List id="categoryList" scroller="{null}" visible="true"
itemRenderer="Renderers.categoryItemRenderer" width="700" borderAlpha="0"
change="categoryList_changeHandler(event)">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
</s:List>
</s:HGroup>
<s:List id="productList" scroller="{null}" contentBackgroundAlpha="0.4" contentBackgroundColor="0xabcdef"
itemRenderer="Renderers.productItemRenderer" width="880" borderAlpha="0" visible="true" horizontalCenter="0"
dragEnabled="false" mouseDown="onMouseDown(event)"
>
<s:layout>
<s:HorizontalLayout/>
</s:layout>
</s:List>
<s:HGroup gap="20">
<s:Group>
<s:Image id="planImage" width="500" height="300" horizontalCenter="0"
toolTip="Drag your items on your Plan and drop them were you plan to install them"
/>
<mx:Canvas width="500" height="300" backgroundAlpha="0.1"
backgroundColor="#abcdef" borderColor="#abcdef" borderStyle="inset"
contentBackgroundColor="#abcdef" cornerRadius="10"
dragDrop="canvas1_dragDropHandler(event)"
dragEnter="canvas1_dragEnterHandler(event)" dropShadowVisible="true"
horizontalCenter="0"/>
</s:Group>
<s:List id="cart" width="200" height="300"/>
</s:HGroup>
I 'm thinking you need add drag initiator should be the item renderer that you are dragging rather than the entire List control.
Not list.selectedItem that simple object that is not like UIComponent or VisualElement you have to point some ui component like group.