How to add labels to horizontal axis in Flex - actionscript-3

I am using a Column Chart to display certain data. The data is provided by an array collection. The array contains 3 elements for the horizontal axis, hence 3 labels are shown on the horizontal axis. I want to show 2 additional labels(i.e. total 5 labels) dynamically on the chart. I there a way to add labels to the horizontal axis.
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Revenue:1200, Expenses:500},
{Month:"Feb", Revenue:1200, Expenses:550},
{Month:"Mar", Revenue:1240, Expenses:475},
]);
/////////////////////////////////////////////////////////
<s:Panel title="Floating Column Chart">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:ColumnChart
dataProvider="{expenses}"
showDataTips="true">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
yField="Revenue"
displayName="Revenue"/>
</mx:series>
</mx:ColumnChart>
</s:Panel>
Here the labels on horizontal axis will be Jan, Feb and Mar. I want to add labels April and May to the horizontal axis dynamically if they are not present in the array collection. Their vertical axis value(in this case revenue) will be 0. I hope the question is clear now.

expenses.addItem({Month:"April"});
expenses.addItem({Month:"May"});
You can just add items to your dataProvider. Is it suitable?

Related

Using RadioButton with RadioButtonGroup in a DataGridColumn (in a quiz application)

I am having some issues to properly use several RadioButton components along with a RadioButtonGroup in my quiz application (when they are rendered via ItemRenderer under DataGridColumn).
The quiz page displays a question along with 4 possible answers which represented by RadioButton components (tied with a unique RadioButtonGroup). A quiz usually contains many multiple choice questions.
Everything works fine until I navigate to the next question and return to the previous question; then I could see my former answer selection in the radio button although when I change my answer and select a different radio button it keeps my old selection and add the new one, which is entirely unreasonable (since RadioButtonGroup should enforce selection of one option only).
Here is how I define the DataGridColumn:
<mx:DataGrid y="141" height="373" dataProvider="{currentQuestion.answers}" id="answersGrid" visible="false" styleName="NoStyleDataGrid" useRollOver="false" headerHeight="0" width="381" x="461" variableRowHeight="true">
<mx:columns>
<mx:DataGridColumn width="20" dataField="key">
<mx:itemRenderer>
<mx:Component>
<mx:Canvas width="100%" height="100%" verticalScrollPolicy="off" horizontalScrollPolicy="off" top="0">
<mx:Script>
<![CDATA[
import mx.core.Application;
]]>
</mx:Script>
<mx:RadioButton id="rb" value="{data.number}" selected="{outerDocument.isSelected(data.number,rb)}" group="{outerDocument.getGroup()}" click="outerDocument.setAnswerState(event,data.number)" width="100%" height="30" x="12" y="0" />
</mx:Canvas>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
I make sure each question has its own unique Group to contain the RadioButton components (as answers) using this code:
public function getGroup():RadioButtonGroup{
if(radioGroupMap[currentQuestion.key]!=null){
return radioGroupMap[currentQuestion.key] as RadioButtonGroup;
}
radioGroupMap[currentQuestion.key] = new RadioButtonGroup();
return radioGroupMap[currentQuestion.key] as RadioButtonGroup;
}
This code works fine as long as I do not go to the next question and return to the previous one.
Appreciate any help on this issue.
Thanks!
After doing some research, it appears that item renderers containing RadioButtons along with RadioButtonGroup on data grid column are not a good design choice. Apparently more item renderers are created than actually needed due to performance reasons which makes the UI act in an unpredictable manner.
I used VBOX instead and created the RadioButton along with the RadioButtonGroup dynamically using ActionScript. Here is some code example:
function populateAnswers(){
var rbg:RadioButtonGroup = new RadioButtonGroup();
for each ( var ans:Answer in currentQuestion.answers){
var row:HBox = new HBox();
var rb:RadioButton = new RadioButton();
rb.group = rbg;
rb.id = ""+ans.number;
var num:int = ans.number;
rb.addEventListener(MouseEvent.CLICK,setAnswerState);
rb.selected = isSelected(ans.number);
row.addChild(rb);
var answerBoby:Text = new Text();
answerBoby.enabled = false;
answerBoby.styleName = "readOnlyTA";
answerBoby.selectable = false;
answerBoby.htmlText = ans.body;
row.addChild(answerBoby);
quizAnswersPanel.addChild(row);
}

Calculating percentage of each sector in Adobe Flex Pie Chart

I have made a donut pie chart in adobe flash builder 4.5 which shows tool tip for each sector during mouse hover. I wanted to know how the application is calculating and displaying the percentage of each sector even though i am just providing values in array collection with no formulas being used in the code given below..
Please Help
My complete code..
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/10/13/creating-donut-shaped-pie-charts-using-the-innerradius-style/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:Script>
<![CDATA[
private function labelFunc(item:Object, field:String, index:Number, percentValue:Number):String {
return item.name + ": " + '\n' + "AVG: " + item.avg;
}
]]>
</mx:Script>
<mx:ArrayCollection id="arrColl">
<mx:source>
<mx:Array>
<mx:Object name="R Winn" obp=".353" slg=".445" avg=".300" />
<mx:Object name="P Feliz" obp=".290" slg=".418" avg=".253" />
<mx:Object name="O Vizquel" obp=".305" slg=".316" avg=".246" />
<mx:Object name="B Molina" obp=".298" slg=".433" avg=".276" />
<mx:Object name="R Durham" obp=".295" slg=".343" avg=".218" />
</mx:Array>
</mx:source>
</mx:ArrayCollection>
<mx:PieChart id="chart"
height="100%"
width="100%"
innerRadius="0.5"
showDataTips="true"
dataProvider="{arrColl}" >
<mx:series>
<mx:PieSeries labelPosition="callout"
field="avg"
labelFunction="labelFunc">
<mx:calloutStroke>
<mx:Stroke weight="0"
color="0x888888"
alpha="100"/>
</mx:calloutStroke>
<mx:radialStroke>
<mx:Stroke weight="0"
color="#FFFFFF"
alpha="20"/>
</mx:radialStroke>
<mx:stroke>
<mx:Stroke color="0"
alpha="20"
weight="2"/>
</mx:stroke>
</mx:PieSeries>
</mx:series>
</mx:PieChart>
</mx:Application>
Here is the screen-shot of the output i.e pie chart
I want to know how the value 23.2% is being displayed as tool tip for the orange sector even though I'm not writing it anywhere in my code..if any function of the sdk is being called to calculate the percentage then where is it??
You're absolutely right - Flex does this for you already.
I'm doing something similar myself so sorry for the necropost. This requires some quick diving into the SDK, specifically to PieSeries.as, line 1772 in the updateMapping function where the percentValue property is set.
for (i = 0; i < n; i++)
{
_renderData.cache[i].percentValue = _renderData.cache[i].number/total;
}
_renderData can be accessed by calling the items property of the series, found on line 468.
override public function get items():Array /* of PieSeriesItem */
{
return _renderData ? _renderData.filteredCache : null;
}
So if you wanted to know the percent of the item at index 3 in your PieSeries, you'd do the following:
var item3Percent:Number = chart.series[0].items[3].percentValue;
You don't need a custom formula to calculate this percentage, it's a standard calculation and one that the pie chart has to preform in order to work what size of the pie to give to each value.
All the information it needs to do this is provided when you set field and dataProvider on the chart object. While I can't provide you with the exact code that is run here is a simple approximation:
function getRowPercentValue(row:Object):Number
{
return (row[field] / getTotalFieldValue()) * 100
}
function getTotalFieldValue():Number
{
var returnVal:Number = 0;
for each(var row:Object in dataProvider)
{
returnVal += row[field];
}
return returnVal;
}
note this is a bit of pseudo-code, the pie chart will be more optimised than this and will do clever things (like use row.valueOf() if field == undefined etc, etc.)
As to why it's displayed there, that will be part of the tooltip renderer, you can see your custom labelFunc working with the lines coming off the chart

Unable to Align data in Datagrid

Hi I have issue with alignment of data in the spark datagrid column after Rendering. All the headers are aligned towards left, however i would like to do the following
1. Middle the column header name.
2. Align the text to right.
3.Freeze the first column so that when i do horizontal scroll, the first column should not move horizontally.
Any help in this regard would be highly grateful.
Thanks and regards
<?xml version="1.0" encoding="utf-8"?>
<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
clipAndEnableScrolling="true">
<fx:Script>
<![CDATA[
import flashx.textLayout.formats.BackgroundColor;
import mx.controls.Alert;
import mx.states.SetStyle;
private const POSITIVE_COLOR:uint = 0x000000; // Black
private const NEGATIVE_COLOR:uint = 0xFF0000; // Red
override public function prepare(hasBeenRecycled:Boolean):void {
if (this.data) {
if (column.labelFunction != null ) {
lblData.text = column.labelFunction( data, column );
setStyle("color", (parseInt(this.data.st1) < 0) ? NEGATIVE_COLOR : POSITIVE_COLOR);
} else {
lblData.text = data[column.dataField];
}
}
}
]]>
</fx:Script>
<s:Label id="lblData" top="9" left="7" textAlign="right"/>
</s:GridItemRenderer>
2/ Align the text to right.
I'll start with the easiest one.
In your custom item renderer, you're still aligning to the left (left="7"). You have two options to fix this:
<s:Label id="lblData" top="9" right="7"/>
will align the Label to the right and cause text overflow to the left
<s:Label id="lblData" top="9" left="7" right="7" textAlign="right"/>
will make the Label take all the available space, align the text to the right and truncate the text if it's too big
1/ Middle the column header name.
I think the only way is to create a custom headerRenderer.
copy the entire DefaultGridHeaderRenderer
find the Label with id "labelDisplay"
change its textAlign property to center
assign the custom headerRenderer:
<s:GridColumn headerRenderer="path.to.CenteredHeaderRenderer"/>
3/ Freeze the first column so that when i do horizontal scroll, the first column should not move horizontally.
I'm afraid this is going to require some serious hacking. If you don't want to dive in and create a customized DataGrid, I think your best bet is to fake it:
create a List to represent the fixed column
create a DataGrid to represent the other columns
turn off the List's vertical scrollbar: you wanna controll the scrolling through the grid
bind their vertical scrolling position: when the DataGrid is vertically scrolled, the List must follow and vice-versa
bind their selected items
do some skinning to make it look like one DataGrid

How to scroll a horizontal tile list by scrolling a HScrollBar?

I have a Tile list with list of user images, and also i have one HScrollBar component. Now if i scroll the Hscroll bar, i want to also scroll the tile list. And also i want the thumb of HScrollBar to adjust its width automatically depending on the number of elements in the data provider of the tile list. How can i do it?
This is how my code is
<components:ExtendedTileList id="lstExpert" horizontalScrollBarStyleName="horizontalScroll" verticalScrollPolicy="off" horizontalScrollPolicy="off"
dataProvider="{expertsOnline}" height="80" width="100%" direction="vertical" maxRows="1"
itemRenderer="ExpertItemRenderer">
</components:ExtendedTileList>
<mx:HScrollBar id="customScrollExpert" styleName="horizontalScroll" minScrollPosition="0" lineScrollSize="20" pageScrollSize="20" y="68"
scroll="hscrollbar1_scrollHandler(event)" visible="true" width="110%" height="5"/>
and my scroll event handler is
protected function hscrollbar1_scrollHandler(event:ScrollEvent):void
{
lstExpert.horizontalScrollPosition=event.target.scrollPosition ;
}

Place an 'addChild' button into grid space of TabNavigator

This question is similar to the post:
"Move Button into grid space of a TabNavigator’s tabs in Flex Builder."
Move Button into grid space of a TabNavigator's tabs in Flex Builder
but with a slight difference. I wish to have a button that adds a child (tab) to the TabNavigator in the grid space (simpler with TabBar, but see below), but will not block tabs as they extend towards the button. This functionality can be seen in every web browser that uses tabs.
In addition I would like to have a scroll button appear if too many tabs are opened, and the ability to close tabs. I have tried using Doug McCune's SuperTabNavigator, which offers most of these features, but it does not offer the addChild button that I am looking for.
Is there a way to add this 'addChild' button to the grid space, or to add the features from SuperTabNavigator to TabBar?
This class will do the trick except for scrolling when there are too many tabs.
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="500" height="400">
<mx:HBox width="100%">
<mx:TabBar dataProvider="{viewstack}"/>
<mx:Button label="+" width="35" click="addTab()"/>
</mx:HBox>
<mx:ViewStack height="100%" width="100%" id="viewstack"/>
<mx:Script>
<![CDATA[
import mx.controls.Label;
import mx.containers.Panel;
//add a new container
private function addTab():void
{
var l:Label = new Label();
l.text = "Panel " + (viewstack.numChildren + 1);
var p:Panel = new Panel();
p.label = l.text;
p.addChild(l);
viewstack.addChild(p);
viewstack.selectedChild = p;
}
]]>
</mx:Script>
</mx:VBox>