AS3 Databinding to Specific property at an index in ArrayCollection - actionscript-3

I have a situation where I want to use databinding from an ArrayCollection to populate text fields in a Flex view.
The ArrayCollection is populated from an SQL Result object. I store the ArrayColelction in my model class using getters and setters like this:
private var _monthlyData:ArrayCollection;
public function set monthlyData(value:ArrayCollection):void{
_monthlyData = value;
}
[Bindable]
public function get monthlyData():ArrayCollection{
return _monthlyData;
}
I use the monthlyData as a dataprovider for a list etc which works fine. I also need to use properties at certain indexs in this collection as text field strings.
When the text field text properties are set I don’t neccesarily have the monthlyData arrayCollection populated yet.
The text fields are set in another outside class with has a singleton reference to this model so I set the fields like so at the moment:
textField.text = _model.monthlyData.getItemAt(3).Month;
I want to setup binding to the array collection instead of just using this assignment method so that when that item in the array is refreshed or the entire arrayCollection is populated or updated , it will update the textField text.
I’m having trouble getting the binding to work.
I’m using bindageTools at the moment but have been also using the built in as3 BindingUtils to little effect.
I can do the following which sets the initial text property correctly, but it wont update when the ArrayCollection changes:
Bind.fromProperty(_model.monthlyData.getItemAt(3),"Month").toProperty(textField, "text");
So if someone could please point me in the right direction as to which way is best to get the binding going in pure AS3 no MXML, I’d really appreciate it.
Cheers
Marco

From the code you provide, I can see that monthlyData is bindable, which is fine. I'll assume that _model is bindable too.
However the getItemAt() method is not bindable (it will not dispatch propertychange events when items change positions in the collection), hence the text property of the text field will not be updated.
What you can do is something like this:
[Bindable]
public var selectedDate3:MyDate;
<s:TextInput id="myTextInput" text="{selectedDate3.month}" />
or the AS equivalent (why you want to make things hard on yourself is beyond me though)
BindingUtils.bindProperty(myTextInput, "text", selectedDate3, "month");
and then programmatically update selectedDate3:
_model.monthlyData.addEventListener(CollectionEvent.COLLECTION_CHANGE, updateSelected);
private function updateSelected(event:CollectionEvent):void {
selectedDate3 = _model.monthlyData.getItemAt(3);
}
Note that the month property of MyDate must also be bindable.
You mention that these fields are in a VGroup. I'm guessing you want to display a top 3 or something. This is still a list. It would be much easier and cleaner to do this with a List or DataGroup and simply filter the ArrayCollection to only display the first 3 items (or whatever rule for the items to be displayed), or configure the DataGroup to display only three items (it has no scrollbar anyway).

Related

separating data in an array for display in Flex

I'm new to flex/flash builder, i need to read in data from a text document, then slice it into pieces i set out in my custom class.
all of this so far worked
var theCustomer:Customer=new Customer(name,address,phoneNo,comment,custNo);
custArray.addItem(theCustomer);
So now what i want to do is display only the name from each entry of the array into a combobox - and then on close it will display all the details into a list box
If i just bind the custArray to the combobox it displays name:address:phoneNo:comment:custNo as i set it out, but like i said i want only the name so how do i separate the name from each Customer entry in the array ??
Any help you be awesome and thanks in advance !!!
If I'm understanding your question correctly, I think you want to set the labelField property on the combobox. This specifies the field in the source data objects to use in the label.
<s:ComboBox dataProvider="{custArray}" labelField="name"/>
The ComboBox has several ways to specify what it should use as the "label" for each item in the dataProvider:
By default, if the elements in the dataProvider has a property named label, and that property contains a String it will display that value.
ComboBox has a labelField property that you can use to tell it where to find the "label" for each item. In your case, you could set the labelField to "name"
ComboBox has a labelFunction property that allows you to use a function (that you write) to specify what text should be displayed for each item.
I suggest using the the labelField, as that seems the most straight forward in this case:
<s:ComboBox dataProvider="{custArray}" labelField="name" />

How to copy Input Text Value into Dynamic Text that is in a MovieClip1 Inside a MovieClip2

Current my code is as such
setcustomlocation.addEventListener(MouseEvent.CLICK,customlocation2);
function customlocation2(e:MouseEvent):void
{
locationinput.text = FlashingWon.Won1.name.text;
}
I'm trying to make it such that it would copy the input text field values into a dynamic text. However, it throws up the error that
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at main/customlocation2()[main::frame1:9]
Which can I only assume that it is not able to communicate with the dynamic text field in the movieclip within another movieclip.
First, you can be 100% sure that it CAN communicate with the dynamic TextField in the MovieClip.
From you description I understand that you wish to copy from input into dynamic. But from your code I see that you take from the dynamic into the input, please check that out:
// This will copy in such a way: input <= wonText
locationinput.text = FlashingWon.Won1.name.text;
// This will copy from input
FlashingWon.Won1.name.text = locationinput.text;
Anyhow, the error that you get has nothing to do with this, it's rather like you already noticed, that one of your TextField is not 'found'. For this I recommend you a best practice: To create instances of the objects you want to use and populate them from the stage through the getChildByName method. This way you will promptly now (specially if you do this on construction or init) if you had any misspelling or miss structure on the childs you want to get.
like so:
var inputText: TextField;
var dynoText: TextField;
In your Constructor or else where at a soon level, give to your vars the proper value:
inputText = getChildByName('locationinput') as TextField;
dynoText = FlashingWon.Won1.getChildByName('name') as TextField;
This way you will soon enough know if one of this 2 textFields were not found under the object you give, and you have only one place to miss spell it. Also you will get code completion on your TextFields.
Finally the copy text part:
dynoText.text = inputText.text;
Hope it helps.
Alright, sorry for the delay, I was out on holidays.
I have opened your example and can see where the problems are:
1) You are trying to reach the FlashingWon when initiating the dynoText on the FIRST frame like so var dynoText = FlashingWon.Won1.getChildByName('name_txt'); BUT the FlashingWon element is ONLY available on the FIFTH frame. Meaning that you cannot refer to it quite yet, unless you add it on the first frame and make in invisible till the fifth frame. (You can make it visible in the goto1 function if you wish after the goToAndStop(5) line)
2) You called the TextField on the Won1 element 'name' which is a restricted sting in AS3, so change it to name_txt or label if you wish and it will work.
Let me know how it worked.

AS3 - Displaying points gained above the player

So, I am adding this text field to my container MC whenever a certain condition is met.
In this case, I am trying to display the number of points gained above a playerMC whenever he grabs a coin. Kind of like the old Mario Games whenever you would step on a Goomba and points would appear above the dead Goomba.
I'd like to be able to assign the "points" text field to a "Text.as" file so I could just control the text field's behaviors from there instead of from within my Document Class.
I know how to create a text field from the document class, but I can't seem to create an empty text field on the stage and then convert it into a movie clip so that I can assign it a base class.
Anyone know of a good way to handle this situation? Any ideas you might have.
It's most efficient to just create the textField via code in the contstructor of your Text.as class. However, if you're set on doing it in the flash IDE... create your dynamic text field, give it an instance name, then convert it to a MovieClip with F8. Go to the library and enter you're new movieClip's properties, set the base class to your Text.as file.
Your class (which encapsulates the textField) should then start out looking something like this:
package {
public class Text extends Sprite {
public var myTextFieldInstanceName:TextField;
public function set text(val:String):void { myTextFieldInstanceName.text = val; }
public function get text():String { return myTextFIeldInstanceName.text;}
public function Text(defaultText:String){
text = defaultText;
}
}
}
In order to set the base class, you need to do the same thing that I recommended you do for your Bullet and Impact movieclips. You perform a linkage by selecting "Export to Actionscript". You can tell it what class to look at for its behavior. Then just addChild it to your playerMC (after adjusting x and y values of course).

JComboBox as CellRenderer does not set the correct value

I'm using a JComboBox as CellRenderer in my JTable.
Everything works fine the JComboBox displays the correct item for the corresponding row.
The problem I am currently working on is that when I choose a new value in the JComboBox (for example row 9) the value is set correctly, but when I try to change the value in the next row, the JComboBox (for example in row 10) automatically sets the value of the row before.
I created a DropDownCellRenderer class which extends JComboBox and implements TableCellRenderer, I thought that is enough, but it seems that the DropDownCellRenderer-object is the same for every row.
table.getColumnModel().getColumn( 3 ).setCellRenderer( new DropDownCellRenderer() );
table.getColumnModel().getColumn( 3 ).setCellEditor( new DefaultCellEditor( new DropDownCellRenderer() ) );
How can I avoid that every row uses the same object?
Looked at your renderer's source code.
I don't think you have to look up the Product by name. The value passed to you is the Product, which is coming from your table model (if it is implemented correctly). Just set the value as selected item and it should work.
To make renderer behave correctly, change its foreground and background colors according to isSelected parameter. The code should look like:
if (isSelected) {
setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
Make your initial array of values an argument of the constructor. This will transform your renderer into universal combobox renderer.
It sounds like you're saving and displaying values within the combo box itself, not from the model of the table. When you set a value and save a combobox value you need to update the model

As3 - Assign class to object on stage

I think the title should make it pretty clear. I was wondering how you can assign a class to an object on stage. As you would do with actionscript:
var objectname:ClassName = new ClassName();
This would make a new object, but the current object already exists, it just needs to be notified that it's of the type "ClassName" so it can inherit it's properties.
I've also tried assigning the "ClassName" in the linkage as either the base path or the class name. But in either situations I get an error saying that the class needs to be unique when I use the same class on multiple objects.
So I would need something like
//example exists on stage
example.class = ClassName
Thanks
I will answer your question with a question : why are you assigning the same class on multiple objects?
If what you want is a common behavior for those objects, you should create your class and assign it has the Base Class on those objects.
I don't think there's a way to do just do that. But I do suggest you look into the decorator design pattern The idea here is that you don't change the class, but you "decorate it" with more functions as needed.
Hope this helps !
You seem to have this the wrong way around. You define a class in order to set specific behavior & properties for an object. In a real life example, if I want to build a radio , I will come up with a radio design & implement it. Now if I need several radios, I will use the same implementation to manufacture them.
If I now wish to turn my radio into a TV , I can't just tell my radio, hey , you're a TV now. I can either decide beforehand that I want a radio/tv object and switch behavior whenever necessary or I can create a new TV object and add the radio functionality to it by adding a radio component to my TV object.
var radio:Radio // your current object
//example 1
radio.switchToTv();
//example 2
var radioTv:Tv = new Tv( radio );