How to point or reference a dynamically created item - actionscript-3

I'm working on an invoice system. I need to add the invoice item dynamically by addchild method as below mentioned
1.select product(combo box)-- Quandity(text box)--Price(text box)--Total(text box)
2.select product(combo box)-- Quandity(text box)--Price(text box)--Total(text box)
My problem is i cant bring the sum amount of all the Total text boxes of each child element..
How to point or refernece a dynamically created item????

You can store all created item in a Array (or Vector), and then access each of them thru a cycle.
For example:
var allPrices:Array = [15.50, 20.24, 36.12];
var allElements:Array = new Array();
for (price in prices) {
// PriceText class is, for example, a movieclip with a textbox inside
var obj:PriceText = new PriceText(price);
addChild(obj);
allElements.push(obj);
}
Now you have all added elements in the allElements array.

Or You can create reference object , like :
class Bind {
public var target:Object;
public var key:String;
public function Bind(t:Object , k:String){
target = t;
key = k;
}
public function get value():* {
return target[key];
}
}
var myItem:SomeClass;
myItem.param = 100;
var bind:Bind = new Bind(myItem,"param");
trace("get myItem value:", bind.value);

Related

Make Objects behave like Radio Buttons in AS3

I would like to implement a very simple way to store a variable containing the last specific "CustomObject" I clicked. I'd like clicks on other objects to be ignored. Take the following sample code for example, given CustomObject extends MovieClip:
//Code within the Document Class:
var square1:CustomObject = new CustomObject();
var square2:CustomObject = new CustomObject();
var square3:CustomObject = new CustomObject();
var triangle1:DifferentObject= new DifferentObject();
square1.x=100; square2.x=200; square3.x=300;
addChild(square1);
addChild(square2);
addChild(square3);
addChild(triangle1);
//Code within the CustomObject Class:
this.addEventListener(MouseEvent.CLICK,radioButtonGlow);
public function radioButtonGlow(e:MouseEvent):void
{
var myGlow:GlowFilter = new GlowFilter();
myGlow.color = 0xFF0000;
myGlow.blurX = 25;
myGlow.blurY = 25;
this.filters = [myGlow];
}
This works great for whenever I click on squares- they light up exactly as expected. However, I'd like to implement a functionality that:
1) Stores the last square I clicked into a variable in the document class
2) Removes the glow from all other squares when I click on another one
Any feedback is greatly appreciated!
I suggest creating a class that acts as a collection of CustomObject instances and manages them in that manner (i.e. ensuring only one of that collection can be selected, etc).
Sample:
public class CustomCollection
{
// Properties.
private var _selected:CustomObject;
private var _items:Array = [];
// Filters.
private const GLOW:GlowFilter = new GlowFilter(0xFF0000, 25, 25);
// Constructor.
// #param amt The amount of CustomObjects that should belong to this collection.
// #param container The container to add the CustomObjects to.
public function CustomCollection(amt:int, container:Sprite)
{
for(var i:int = 0; i < amt; i++)
{
var rb:CustomObject = new CustomObject();
rb.x = i * 100;
_items.push(rb);
container.addChild(rb);
}
}
// Selects a CustomObject at the specified index.
// #param index The index of the CustomObject to select.
public function select(index:int):void
{
for(var i:int = 0; i < _items.length; i++)
{
if(i == index)
{
_selected = _items[i];
_selected.filters = [GLOW];
continue;
}
_items[i].filters = [];
}
}
// The currently selected CustomObject.
public function get selected():CustomObject
{
return _selected;
}
// A copy of the array of CustomObjects associated with this collection.
public function get items():Array
{
return _items.slice();
}
}
Then you can revise your code in the document class to something like:
var collection:CustomCollection = new CustomCollection(3, this);
collection.select(1);
You will need to add your own logic for the click event that deals with selecting the buttons. I suggest adding an index property to each CustomObject as well as a reference to the collection it was added to. That way, you can simply add the click event into the CustomObject class and have the handler function something like:
private function _click(e:MouseEvent):void
{
_collection.select(index);
}

How to change the value of an item in a Flex ArrayCollection

I have an ArrayCollection with values predefined. I want to assign a new value to items in the arrayCollection. This new value is define after datagrid ItemEditEnd.
private var tabRV :Array=[
{thevalue:"25",height:"115",col:"foo"},
{thevalue:"45",height:"115", col:"foo"},
{thevalue:"15",height:"115",col:"bb"},
{thevalue:"95",height:"115", col:"aa"},
];
[Bindable]
public var acRDV:ArrayCollection=new ArrayCollection(tabRV);
My ItemEditEnd, look like this:
private function getCellInfo(event:DataGridEvent):void {
// Get the new value from the editor.
var newVal:String = event.currentTarget.itemEditorInstance.htmlText;
// Get the old value.
var oldVal:String =
event.currentTarget.editedItemRenderer.data[event.dataField];
DP_LISTEREDVCLI[event.rowIndex].thevalue=newVal;
DP_LISTEREDVCLI[event.rowIndex].col=1;
trace("xml new val "+DP_LISTEREDVCLI[event.rowIndex].[event.columnIndex]+"/"+DP_LISTEREDVCLI[event.rowIndex].[DP_LISTEREDVCLI.length]);
}
I hope to create a generic function, DP_LISTEREDVCLI[event.rowIndex][event.columnIndex] but it doesn't work. Indeed in this case a new attribute is creating [event.columnIndex value]
Thanks for helping

How can I copy an ArrayCollection of transfer objects in actionscript?

public function create():ArrayCollection{
var index:int = 0;
var data:ArrayCollection = new ArrayCollection();
var length:int = originalData.length;
for(index; index < length; index++){
data.addItem(originalData[index]);
}
return data;
}
originalData is the original state of my data from database.
data is a copy of originalData used to be manipulated as the provider for my List component.
There's a button I use to call the create() function above, that
would mean, I want to revert all changes in data, and go back to
everything I have in originalData.
But when I debug my function, originalData has all the changes made in data.
When I use
list.selectedItem.thing = "new string";
is supposed to modify data[index].thing, because data is my List.dataprovider. but it changes originalData[index].thing also and this collection wasn't used for anything, except for creating a copy of itself!
I don't know why this happens. I didn't know how to phrase this behaviour as a google query.
Please, if you don't understand the question, comment it so I can try and make it clearer. This has consumed more time than its functionality is worth.
EDIT:
I've also tried this, but it doesn't work:
public function create():ArrayCollection{
var index:int = 0;
var data:ArrayCollection = new ArrayCollection();
var length:int = originalData.length;
for(index; index < length; index++){
// initializing a Item object.
var dataItem:Item = new Item();
dataItem = originalData[index] as Item;
data.addItem(dataItem);
}
return data;
}
EDIT 2:
Based on your answers and some research I came up with this generic function to copy arrayCollections made of custom objects.
public static function copy(objectClassName:String, objectClass:Class, arrayCollection:ArrayCollection):ArrayCollection{
var index:int = 0;
var length:int = arrayCollection.length;
var copy:ArrayCollection = new ArrayCollection();
for(index; index < length; index++){
registerClassAlias(objectClassName,objectClass);
copy.addItemAt(ObjectUtil.copy(arrayCollection.getItemAt(index)) as objectClass,index);
}
return copy;
}
As Tom says, this is because AS3 passes by reference. If you don't want to modify the original values then you should, again as Tom says, create copies of them.
Fortunately, AS3 has a utility to do this -- ObjectUtils.copy. Try this code instead of your original:
public function create():ArrayCollection{
var index:int = 0;
var data:ArrayCollection = new ArrayCollection();
var length:int = originalData.length;
for(index; index < length; index++){
data.addItem(mx.utils.ObjectUtil.copy(originalData[index]));
}
return data;
}
Do take note that copy() returns a generic Object. If you want to access any of its properties in a type-safe manner you'll have to cast it to its type.
A bit more about the pass-by-reference deal. Let's say we have items a, b, and c floating around in memory. You put them into an array(originalData). originalData now contains references to a, b, and c. You then create an ArrayCollection and insert (again) references to a, b, c. Objects a, b, and c aren't what's being stored in either the array or the ArrayCollection. So when you update originalData[0] you're getting a reference to an object (a), and updating it.
Likewise when you update ArrayCollection.getItemAt(0) you're getting the same reference and updating the underlying object which is why you're getting the behavior you're getting. Making a copy and inserting it means you're referencing an entirely new object.
I am not used to actionscript, but it looks to me like you are putting references to objects from one arrayCollection to another arrayCollection. So if you change those objects, this will be reflected in both arrayCollections since they refer to the same objects.
To avoid this you should make copies from the original objects to put in the new arrayCollection.
To create a deep copy of an array and keep the type, use the following method:
public static function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
This is the way proposed by Adobe.
Update: idea for a type safe copy function
public static function copyTypeSafe( ac:ArrayCollection ):ArrayCollection
{
var cloneAc:ArrayCollection = new ArrayCollection();
if( ac.length == 0 ) {
return cloneAc;
}
var className:String = getQualifiedClassName( ac.getItemAt(0) );
registerClassAlias( className, (getDefinitionByName( className ) as Class ) );
for each (var obj:Object in ac)
{
cloneAc.addItem( ObjectUtil.copy( obj ) );
}
return cloneAc;
}
You need to do a registerClassAlias call for each of the classes inside of your collection, then just use the function clone with the ByteArray suggested above and it will work fine. The key is to do a registerClassAlias call for each type inside of the ArrayCollection which you want to maintain. In my case:
var productGroupClassName:String = getQualifiedClassName(ProductGroup);
registerClassAlias( productGroupClassName, ProductGroup );
var productClassName:String = getQualifiedClassName(Product);
registerClassAlias( productClassName, Product );
//Need to create a copy so the original values will not be altered
dataProvider = copyTypeSafe(EnalityData.productsInfo);

ActionScript - Get Instance Name From Constructor Without Passing Parameters?

is it possible to obtain the instance name of a class from the class without having to manually pass the instance name as a string parameter to the class constructor?
//Create New SizeClass
var big:SizeClass = new SizeClass();
//-------------
package
{
public class SizeClass
{
public function SizeClass()
{
trace( //-- Instance Name "big" --// );
}
}
}
No, it is not possible to know anything about the containing code block during a constructor, save what you can learn from the stack trace (though that's not available except in the debugger version of Flash). Even if you had a global access point for the containing class, it still would not allow for that access.
Think of a constructor like a method call. In a line of AS, it will be called before the assignment. Eg: var a:Foo = new Foo() the Foo is created (the constructor completes), and then a is populated with whatever just happened. After that point a will remain agnostic of its context (because of encapsulation) unless it is told about it (this is even true on a DisplayObject -- try this( var mc:MovieClip = new MovieClip(); trace( mc.root ) //this will be null ).
I'm keeping this because it is useful albeit not useful to your original answer.
You can always get the name of a class with getQualifiedClassName from the flash.utils package. You can't get a DisplayObject's until well after it has been constructed, but you can simulate this by (I believe) overriding function set name( value:String ):void. If that doesn't work, then try finding it after Event.ADDED and/or Event.ADDED_TO_SAGE.
The instance name isn't very important. You'd better store references of the instances inside an array.
var sizes:Array = new Array();
var big:SizeClass = new SizeClass();
sizes.push( big );
When you want to access them, you can loop through the array.
for (var i:uint = 0; i < list.length; ++i)
{
var size:SizeClass = list[i] as SizeClass;
trace( size );
}
BTW: Instead of an instance name it is possible to add an automatic index to your class.
package
{
public class SizeClass
{
private static var global_index:int = 0;
public const INDEX:int = global_index ++;
}
}
Which you can access like this:
var big:SizeClass = new SizeClass();
trace(big.INDEX) // 0
var small:SizeClass = new SizeClass();
trace(small.INDEX)// 1
source: http://blog.stroep.nl/2010/08/auto-increment-as3-class/

Changes to AS3 array of string variables doesn't update the variables themselves

I have to assume I am missing something simple, or I am not understanding something, but I can't seem to figure this.
I have a list of strings that I add to an array, then attempt to set those values in a for-loop using data that I read in. The array gets updated, but the values the array contains do not. I also have an array of buttons that I update this same way that works great, but strings don't seem to work the same way. I have tried moving the string array to give it full scope, and still nothing... What am I missing?
public class test extends Sprite
{
// Declare a list of strings
protected var title0:String = undefined;
protected var title1:String = undefined;
protected var title2:String = undefined;
protected function onDataLoad(evt:Event):void{
var titleArray:Array = new Array(title0,title1,title2); // Array of strings
for(i=0; i<=evt.target.data.count; i++){
titleArray[i] = evt.target.data["title"+i]; // attempt to set the title values
}
}
protected function function0(e:Event):void {
trace("My title is: " + title0); // title0 is null
}
}
It has to do with how AS3 stores Array elements. You would need to explicitly set both the instance property (title1, title2, title3) and the associated array element (array[0], array[1], array[2]) to achieve what you want. Or, you could drop the instance properties (title0, title1, title2) completely and just use the array to store your values. Something like:
public class test extends Sprite
{
protected var _titleArray:Array = [];
protected function onDataLoad(evt:Event):void{
for(i=0; i<=evt.target.data.count; i++){
// set the title values
_titleArray[i] = evt.target.data["title"+i];
}
}
protected function function0(e:Event):void {
trace("My title is: " + _titleArray[0]);
}
}