Copy link to clipboard
Copied
Hello All,
I desperately need your help. I have created dynamically created check boxes depending on my selection for my android app using the following code snippet.
for(var i:int=0 ; i<data.PromptText.length; i++)
{
chk = new CheckBox();
chk.label= data.PromptText.getItemAt(i);
chk.name=data.ResponsePromptID.getItemAt(i);
chk.addEventListener(MouseEvent.CLICK,ClickEvent);
chk.width = 1000;
chk.height = 50;
addElement(chk);
}
Now after click on each check box, I need to check which check box of the list of check boxes created ?
Please help me, this is driving me nuts.
This is the big problem, as you loop through _every_ answer that is displaying, you do this:
so.data = event.target.id; // so is my shared object.
so.data.status = event.target.selected;
so.flush();
So... what you are doing here is:
1. Set data to the target id that is being checked... i will only ever be an integer from 0 to the number of data items so will overwrite the previous question data
2. Setting data.status to the selected value of the current item... so if you have four items, it will b
...Copy link to clipboard
Copied
Hi,
I see you have "addElement" rather than "addChild", so this is Flex, right?
So there is an easier way to do that in any case, I think.
For example, you could use CheckBox to create a custom renderer and then use your PromptText IList as dataProvider to a list, something like this:
1. Your item renderer
[code]
<?xml version="1.0" encoding="utf-8"?>
<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"
width="100%" mouseDown="itemrenderer1_mouseDownHandler(event)"
>
<fx:Script>
<![CDATA[
/**
* Override selected to provide bindable property
* as ItemRenderer.selected is not flagged as bindable.
*/
override public function set selected(value:Boolean):void {
super.selected = value;
cbSelect = value;
}
[Bindable] protected var cbSelect:Boolean = false;
/**
* Override to set ctrlKey and so to leverage Adobe's existing
* click to toggle functionality.
*/
protected function itemrenderer1_mouseDownHandler(event:MouseEvent):void
{
// ctrlKey is used by the component to toggle multiple selection
// behaviour but, for checkbox, we want to treat all as a multiple
// selection toggle, so set it to true.
event.ctrlKey = true;
}
]]>
</fx:Script>
<!--
Use CheckBox with selection tied to render selection
and mouseEnabled=false to prevent conflicts with CheckBox
own interactivity.
-->
<s:CheckBox label="{data}" selected="{cbSelect}"
top="4" bottom="4" left="4" right="4"
mouseEnabled="false" mouseChildren="false"
/>
</s:ItemRenderer>
[/code]
2. The application that uses the item renderer:
[code]
<?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" minWidth="955" minHeight="600"
layout="{vl}">
<fx:Script>
<![CDATA[
import flashx.textLayout.formats.VerticalAlign;
import mx.collections.ArrayCollection;
import mx.collections.Sort;
import spark.components.CheckBox;
import spark.events.IndexChangeEvent;
import spark.layouts.VerticalLayout;
private var promptBuilder:int = 0;
private var idBuilder:int = 0;
[Bindable] protected var PromptText:ArrayCollection = new ArrayCollection(
["Prompt text 1...","Second Prompt text...","Third prompt as text...","Prompt...","Prompt...","Prompt..."]
);
[Bindable] protected var ResponsePromptID:ArrayCollection = new ArrayCollection(
[++idBuilder,++idBuilder,++idBuilder,++idBuilder,++idBuilder,++idBuilder]
);
/**
* Change handler called whenever an item is selected or deselected.
*/
protected function list1_changeHandler(event:IndexChangeEvent):void
{
displayCurrentSelection();
}
/**
* Simple demonstration of interrogating list to find what is and is
* not selected.
*/
protected function displayCurrentSelection():void {
var s:String = "STATUS OF LIST AT "+(new Date).toTimeString();
// selectedIndices returns a list of the data indices of any selected items.
var vs:Vector.<int> = listDisplay.selectedIndices;
if(!vs.length) {
// If zero length, nothing selected
s += "\n(No selection.)";
} else {
// If length, then we have work to do.
// 1. Indices populated in order of clicking, but we want them
// in order of display, so sort.
vs = vs.sort(sortOnInt);
// 2. Now loop through to see what is and isn't there.
for(var i:int=0;i<vs.length;i++) {
// Index is position in the data set that was selected
// This should match the parallel array of ids.
var index:int = vs;
s += "\nID:"+ResponsePromptID.getItemAt(index)+" = "+PromptText.getItemAt(index);
}
}
// Populate the display variable.
currentSelection = s;
// Simple sort function.
function sortOnInt(a:int,b:int):int {
return a>b ? 1 : -1;
}
}
[Bindable] protected var currentSelection:String;
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<s:VerticalLayout id="vl" paddingBottom="10" paddingTop="10" paddingLeft="10" paddingRight="10" />
</fx:Declarations>
<s:Label text="Click to toggle item selection" fontWeight="bold" />
<s:List id="listDisplay"
layout="{new VerticalLayout}" width="100%"
labelField="label" dataProvider="{PromptText}"
itemRenderer="CBItemRenderer"
allowMultipleSelection="true"
change="list1_changeHandler(event)"
/>
<s:Label text="{currentSelection}" width="100%" />
</s:Application>
[/code]
Copy link to clipboard
Copied
Hey Gaius Coffey,
Thank you so much for you reply. I can use your code for the futre, this will help for sure. I need help with saving the status of the check boxes.I will try explain my situation some more. I have a home view which has list view which has set of questions and when I click on one of the question from the List Items, I used
navigator.pushView(views.Questions, tripList.selectedItem, null, fadeTrans);
and move a view where the answers in views.Questions ( checkboxes are being populated). The user can choose multiple answers. For doing that i wrote the following code
private function init():void
{
if(data ==null)
{
navigator.popToFirstView();
}
else
{
for(var i:int=0 ; i<data.PromptText.length; i++)
{
chk = new CheckBox();
chk.label= data.PromptText.getItemAt(i);
chk.name=data.ResponsePromptID.getItemAt(i);
chk.id = data.ResponsePromptID.getItemAt(i).toString();
chk.addEventListener(MouseEvent.CLICK,ClickEvent);
chk.width = 1000;
chk.height = 50;
addElement(chk);
if(so.size >0)
{
// This is where I am trying to save the check box status.
if(so.data !=null)
{
ItemId.addItem(so.data);
for(var m:int = 0; m<ItemId.length;m++)
{
trace(ItemId.getItemAt(m));
if(chk.id ==ItemId.getItemAt(m))
{
//var elem:CheckBox = this[so.data.id];
//getChildByName(so.data.idvalue);
//chk1.getChildByName("237").s
chk.selected=so.data.status;
}
}
}
Now when the user clicks on the check boxes the following is invoked.
private function ClickEvent(event:MouseEvent):void
{
for(var i:int=0 ; i<data.PromptText.length; i++)
{
chk1 = new CheckBox();
chk.label= data.PromptText.getItemAt(i);
chk1.name=data.ResponsePromptID.getItemAt(i);
if(event.target.selected)
{
if(event.target.name ==chk1.name )
{
so.data = event.target.id; // so is my shared object.
so.data.status = event.target.selected;
so.flush();
parameters["ResponseValue"]= ResultsQuestion.getItemAt(3).ResponseValue;
}
}
But, when I try click on any check box the check box status is retained for the same question when i revisit the question , when I check the answers from another question the status of the check box of the previous question are not kept. So, it is some problem with persisting data. I used persistant manager that did not help.
I am sorry for the long post. But, please help me with retaining the status.
Thank you
Copy link to clipboard
Copied
This is the big problem, as you loop through _every_ answer that is displaying, you do this:
so.data = event.target.id; // so is my shared object.
so.data.status = event.target.selected;
so.flush();
So... what you are doing here is:
1. Set data to the target id that is being checked... i will only ever be an integer from 0 to the number of data items so will overwrite the previous question data
2. Setting data.status to the selected value of the current item... so if you have four items, it will be set four times, and only the value of the last one will be stored
Whereas, if I understand you, you want to do something like this instead (pseudo-code, you'll have to fill in the blanks...):
[code]
var questionData:Object = new Object();
questionData.questionId = theIdOfThisQuestion;
for(var i:int=0 ; i<data.PromptText.length; i++) {
//... stuff you were doing before
if(event.target.selected) {
questionData[event.target.id] = true;
}
//... rest of the stuff you were doing before
}
so.data['question'+questionData.questionId] = questionData;
so.flush();
[/code]
That way, you are generating a unique, indexed store of all the correct answers by question id rather than constantly overwriting the same values.
G
Copy link to clipboard
Copied
You are a saviour, as you said I changed the pseudo-code to meet my requirement and it worked Thank you so much . Now, I have realized that OnClick event is not triggered if some revisits the question and unchecks the anwers before submiting it. So, even if they unchecked a particular answers, it shows the check mark. I couldnot find
chk.addEventListener(OnCheckboxChange,ClickEvent); or something like that
instead of
chk.addEventListener(MouseEvent.CLICK,ClickEvent);
Please help.
Thank you
Copy link to clipboard
Copied
Yes, checkbox dispatches an Event.CHANGE.
G
Copy link to clipboard
Copied
Well, I was missing the Else for the IF which checked (event.target.selected). Now I can access the else part. Thank you, you are awesome.