Low Overhead Dynamic Tab/ViewStack in Flex? - apache-flex

Suppose I have a ViewStack like this:
<mx:ViewStack id="s" left="5" right="5" bottom="5" top="0" width="100%" height="100%" creationPolicy="all" minHeight="0">
<mx:Repeater id="repeater" dataProvider="{dp}" height="100%" width="100%" minHeight="0">
<mx:Box id="bx" label="{repeater.currentItem.label}" width="100%" height="100%" minHeight="0">
<mx:Label minHeight="0" width="100%" height="100%" label="bob" />
</mx:Box>
</mx:Repeater>
</mx:ViewStack>
With a large number of items in the stack (each having a large number of panels, databinding, etc), this gets extremely slow. The Repeater seems to trigger creation of all children regardless of the creationPolicy of the viewStack itself.
Is there a readymade solution to this efficiency problem? I can think of some ways to solve it with a custom component, but I'm wondering if there's an off the shelf solution for cases where the inner values really need to be dynamic (backed by an ArrayCollection) like this.

Assuming that all your stacked views are identical except for some specific data displayed in them a possible solution would be to ditch the viewstack and set up all your controls to bind to an array collection, then whatever control you would use to change your viewstack could instead update your array collection.

Trying using a List with an itemRenderer. Repeaters are notorious for terrible performance.

Related

What is the difference between VGroup container and Group container with nested VerticalLayout in fle4?

I am a beginner for flex. Now i am trying samples using the layout.
See the following scenario,
<s:VGroup horizontalAlign="center">
<s:Label text="VGroup Container"/>
<s:Button label="One"/>
<s:Button label="Two"/>
<s:Button label="Three"/>
</s:VGroup>
<s:Group>
<s:layout>
<s:VerticalLayout horizontalAlign="center"/>
</s:layout>
<s:Label text="Group with VerticalLayout"/>
<s:Button label="One"/>
<s:Button label="Two"/>
<s:Button label="Three"/>
</s:Group>
Is it having any differences? If it's having, please share it with me. Otherwise tell me which one is better or which one is correct?
Thanks in advance.
The two are equivalent, mostly...
In general if I know the group layout orientation I'll use VGroup/HGroup rather than Group and layout, but that's just my preference, I don't think there's a significant performance difference.
I have places where I need to change orientation, so I'll use Group and change the layout based on the orientation state. VGroup/HGroup won't let you change the layout associated with them.

Adobe Flex List Itemrenderer: Cannot Scroll List

I have have successfully set up a list that pulls users from a database and displays them in a list. I'm currently customising the list with an itemrenderer and it's going well. I can pull a user's profile picture, then to the right of it I'll display their name and underneath is their age. The problem is that I can only fit 4 results into the list and I can see the top of the 5th, but there's no scroll bar. I would show a print screen but I populated my database with real info about my friends and their facebook details, so i'd rather not.
In my main mxml programme I have the following code:
<s:List id="resultList" includeIn="loggedin" x="120" y="246"
width="100%" itemRenderer="userList">
<s:layout>
<s:VerticalLayout useVirtualLayout="true" requestedMinRowCount="1"/>
</s:layout>
<s:AsyncListView list="{getUserResult.lastResult}"/>
</s:List>
In userList.mxml I have the following code:
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true">
<s:Image id="fbImg" source="http://graph.facebook.com/{data.facebookid}/picture?type=normal" x="0" y="0"/>
<s:Label id="usernameLbl" x="120" y="0" fontFamily="Calibri" fontSize="25" fontWeight="bold" text="{data.firstname} {data.lastname}"/>
<s:Label id="ageLbl" text="{data.dob}" x="120" y="40" />
</s:ItemRenderer>
Does anybody know why I cannot scroll all of my results? I'm sure it's something very simple that I do not know about.
EDIT: I'm so sorry for the horrible formatting. I can't seem to get my code to display nicely.
Assign a height to your list and all will be right in the world. If you don't, it assumes it can extend past the bottom of your page to show all the data even if you cant see it.
<s:List id="resultList" includeIn="loggedin" x="120" y="246"
width="100%" height="100%" itemRenderer="userList">
<s:layout>
<s:VerticalLayout useVirtualLayout="true" requestedMinRowCount="1"/>
</s:layout>
<s:AsyncListView list="{getUserResult.lastResult}"/>
P.S. Great question with lots of detail and perfect amount of code.
I had a problem with List seeing the percent height (height="100%"). So, I had to set it using something like height="{myContainer.height}" and it worked.

How to reach elements of an inline component in flex?

I have a problem with inline components. I want to reach an inline component from another one.. From the first component, i want to change "enable" value of the linkbutton named "Add" which is in second component. Altough i gave "id" and "className" to second one, i could reach neither it nor its elements.. is there a way to do this?
*in first component there is a text input in "CodedDescriptionItemEditor" component. I want to validate it and according to validation enable the button that i mentioned above..
These all are in a datagrid by the way. In datagrid, there is always a row that you can enter data and via the "Add" button you can save it. After save it seems as text..
Thank you..
Here is my code:
<mx:columns>
<mx:DataGridColumn headerText="{Problem}" wordWrap="true" textAlign="left" sortable="false">
<mx:itemRenderer>
<mx:Component>
<mx:VBox>
<mx:ViewStack selectedIndex="{outerDocument.index(data)}" >
<mx:HBox>
<mv:CodedDescriptionItemEditor id="editor" codePM="{outerDocument.problemListPanelPM.getProblemDescPM(data)}"
width="100%" styleName="phrFormItemInput"/>
</mx:HBox>
<mx:HBox>
<mv:CodedDescriptionItemRenderer id="renderer" codedDescPM="{outerDocument.problemListPanelPM.getProblemDescPM(data)}" />
</mx:HBox>
</mx:ViewStack>
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn headerText="" textAlign="center" editable="false" width="50" resizable="false" sortable="false">
<mx:itemRenderer>
<mx:Component className="buttonColumn">
<mx:ViewStack selectedIndex="{outerDocument.index(data)}" >
<mx:HBox horizontalAlign="center" width="100%">
<mx:LinkButton id="Add" icon="#Embed('img/add.png')"
toolTip="{outerDocument.Add_Problem}"
click="outerDocument.addHandWritten()"
enabled="false" />
</mx:HBox>
<mx:HBox horizontalAlign="center" width="100%">
<mx:LinkButton id="Delete" icon="#Embed('img/delete.png')"
toolTip="{outerDocument.Remove_problem}"
click="outerDocument.removeProblem()"/>
</mx:HBox>
</mx:ViewStack>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
</mx:columns>
Inline components in MXML are not instances but classes. So that kind of "reaching" has no sense. To combine this knowledge together to operate them I recommend you the following simple rule (which I follow and haven't problems with understanding class/instances relations):
Do not use inline components in MXML excluding simple cases on a
prototyping stage.
So in your case I recommend you to extract inline components into separate MXML classes and throw all the outerDocument references (you can replace them with events with bubbling). After that I think it will be much easier to understand and improve your design and find appropriate solution.
Another advice is use data-driven way to operate with renderers. This way is about operating data items of data provider but not getting and setting data from outer document directly. Use data binding to bind changed data between different item renderers in different columns.
In this case, you might want to keep a boolean var isAddEnabled in your outerDocument and change your enabled as below:
enabled="{outerDocument.isAddEnabled}"
Change this isAddEnabled based on your validation criteria.
As you don't want it to be applied to all your items, either keep a property in your dataProvider(preferred) OR maintain another collection of same length as your dataProvider (not recommended).

Weird display when scolling images inside List component in Flex

I have a list that displays photos like them:
<s:List id="thumnPhotosList"
dataProvider="{_model.photoAlbumToCreate.photos}"
height="450"
itemRenderer="PhotoRenderer" >
<s:layout>
<s:TileLayout orientation="columns"
requestedRowCount="4"
requestedColumnCount="3" />
</s:layout>
</s:List>
and PhotoRenderer has a code like this:
......
<mx:Image source="{_model.url + theAlbumPhoto.thumbPhotoURL}"
visible="{theAlbumPhoto.ready}"
maintainAspectRatio="true"
maxWidth="{Constants.DEFAULT_ALBUM_PHOTO_WIDTH}" maxHeight="{Constants.DEFAULT_ALBUM_PHOTO_HEIGHT}" />
........
Which works fine except when the number of photos get high and the scroll bar appears it starts behaving weirdly: it start showing photos different than the ones it supposed to and if I scroll back to beginning and scroll again to new photos other ones appears sometimes the correct ones and sometime not. Not sure how to resolve this, any ideas? you can also recommend different way than using s:List if that makes it easier.
I had the same problem with text List, i think its padding issue, organize the pading for all components it may help.
As I couldn't figure out what the problem was and couldn't reproduce it on stand alone application. I came up with the following code that solved the issue:
<s:Scroller id="photoScroller"
width="100%"
visible="{_model.photoAlbumToCreateOrUpdate.photos.length > 0}"
horizontalScrollPolicy="off" verticalScrollPolicy="auto"
skinClass="com.lal.skins.PhotoAlbumScrollerSkin"
top="50" bottom="0">
<s:DataGroup id="thumnPhotosList"
dataProvider="{_model.photoAlbumToCreateOrUpdate.photos}"
itemRenderer="AlbumPhotoThumbRenderer" >
<s:layout>
<s:TileLayout orientation="rows"
requestedRowCount="4"
requestedColumnCount="4" />
</s:layout>
</s:DataGroup>
</s:Scroller>
I had this same issue with an Image component in a custom item renderer I was using in a TileList. I fixed it without really knowing how, but the problem was the source property of the Image component in the item renderer.
The idea with item renderers is to use the data variable to access the item feeding the renderer. What do the _model and theAlbumPhoto variables refer to in your renderer? What I ended up doing was changing the source property to something more like data.image_path, and it decided to start working.
If you're happy with your solution, hopefully this can at least be of help to someone else.

Flex: when hiding components in flex

When I set a component to visible=false the component hides, but how do I get it to take no space (get the container it belongs to to resize??)
<mx:HBox width="100%" height="100%">
...
</mx:HBox>
<mx:HBox width="100%" id="boxAddComment" visible="false" >
<mx:TextArea id="txtComment"/>
<mx:Button label="Spara" click="addComment();"/>
</mx:HBox>
When boxAddComment is visible=false I want the first HBox to take 100% height.
use the includeInLayout property. e.g.
<mx:HBox width="100%" height="100%">
...
</mx:HBox>
<mx:HBox width="100%" id="boxAddComment" visible="false" includeInLayout="false" >
<mx:TextArea id="txtComment"/>
<mx:Button label="Spara" click="addComment();"/>
</mx:HBox>
Using includeInLayout ="true" or "false" will toggle the space that it takes in the flow of items being rendered in that section.
Important note: If you don't specify visible="false" when using includeInLayout = "false" then you will usually get something that is undesired which is that your item (boxAddComment) is still visible on the page but stuff below id="boxAddComment" will overlap it visually. So, in general, you probably want "includeInLayout" and "visible" to be in synch.
Ross Henderson's suggestion in binding includeInLayout with boxAddComment.visible works great with Flex 3.0 but I found that it's not working in Flex 3.6 (I saw a posting that it actually stops working since Flex 3.3).
Just fyi.

Resources