I'm using mapping utils to load some mega JSON data. I know how to detect changes with an 'update' callback.
But how do I compare the old value with new value? In the 'update' callback I get access only to new value.
Of course - when I put update to JSON - I use mapping utils again.
I'd like to know whether the value increases or decreases. How to do this?
An update callback for the ko.mapping plugin takes one options argument, which is an object containing
data
parent
target
The parent object still holds the old value.
var mapping = {
'prop':
update: function(options) {
var oldval = options.parent.prop;
var newval = options.data;
// do something that uses oldval and newval here
return newval;
}
}
Related
I want to be able to access a instance on the stage dynamically by looping through an array containing Strings that describes the path.
private var clockKeeper:Array = new Array("LB.anim.clock.lbclock");
trace(stage.LB.anim.clock.lbclock.text);
for (var key in clockKeeper) {
trace(stage[clockKeeper[key]].text);
}
When i access it manually with the first trace statement, it works.
When i do it dynamically it seems like Flash tries to find an object named "LB.anim.clock.lbclock" not LB.anim....
How can i change this behaviour and make it work?
You should try splitting the "path" which should then consist of locally available names, and address each object in order. "Locally available names" means there should be stage.LB, and that object should have a property anim, etc etc.
function getObjectByPath(theRoot:DisplayObjectContainer,
thePath:String,separator:String='.'):DisplayObject
{
var current:DisplayObjectContainer=theRoot;
var splitPath:Array=thePath.split(separator);
while (splitPath.length>0) {
var named:DisplayObject = current.getChildByName(splitPath[0]);
var addressed:DisplayObject=current[splitPath[0]];
// either named or addressed should resolve! Otherwise panic
if (!addressed) addressed=named; else named=addressed;
if (!named) return null; // not found at some position
splitPath.shift();
if (splitPath.length==0) return named; // found, and last
current=named as DisplayObjectContainer;
if (!current) return null; // not a container in the middle of the list
}
// should never reach here, but if anything, just let em
return current;
}
This provides two ways of resolving the path, by name or by property name, and property name takes precedence. You should then typecast the result to proper type.
Yes, call this as follows:
trace((getObjectByPath(stage,clockKeeper[key]) as TextField).text);
I have an array collection object 'invArrayCol' which holds some data. I also have a datagrid. I have set dataProvider as invArrayCol.I displays the data properly when i use it with data grid. But the same invArrayCol shows null when used anywhere other than datagrid. I wrote this code
protected function titlewindow1_creationCompleteHandler(event:FlexEvent):void
{
Cgt=new CgtSRObject();
var autoobj:CSAutoNumberType=new CSAutoNumberType();
autoobj.addEventListener(ResultEvent.RESULT,getInvNubmer);
autoobj.getInvNo(invoiceType);
trace(robj.salesPerson_Id);
getSalesReturnCgt.token=csInvoicePrint.getCgtData(robj.receive_Id);
getSalesReturnCgt.addEventListener(ResultEvent.RESULT,getInvArrList);
trace(Cgt.sr_no);
datagrid_dataprovider=new ArrayCollection();
datagrid_dataprovider=invArrayCol;
calculateTotal();
}
This 2 lines set data to invArrayCol
getSalesReturnCgt.token=csInvoicePrint.getCgtData(robj.receive_Id);
getSalesReturnCgt.addEventListener(ResultEvent.RESULT,getInvArrList);
But here it gives value of invArrayCol as null.
datagrid_dataprovider=new ArrayCollection();
datagrid_dataprovider=invArrayCol;
Please tell me some way out of this.
The ResultEvent's result may return an ObjectProxy, in case the data is of length 1. Casting via 'as' would lead to a silent failing of the cast. So simply checking the type of the result would let you determine if the result can be used directly or if you have to wrap an ArrayCollection around it.
// This happens asynchronously, should have no effect in the function
getSalesReturnCgt.addEventListener(ResultEvent.RESULT,getInvArrList);
Also, the
// datagrid_dataprovider=new ArrayCollection(); // This line is obsoloete
datagrid_dataprovider=invArrayCol; // invArrayCol will get its value later
So, it looks like your expectation is for some code to have it executed synchronously, but it is always working asynchronously.
I have written a function which is recursively called. I have maintained an array in which values are pushed with a listener of an event. But the problem is function is returned first without array increment and the listener is executed later.
public function getAllChilds(seltem:XML, allChilds:Array): Array
{
if(//the childs of selected item if need to retrive from server)
var viewChildrenJobsService : HTTPService = new HTTPService();
viewChildrenJobsService.url = // here is my url ;
viewChildrenJobsService .addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void {
// now on this result event i got all childs of selected item.
for each(var childJob :XML in seltem.children())
{
allChilds.push(childJob);
if (//the childs of childJob need to retrive from server)
allChilds = getAllHierarchicalChilds(childJob, allChilds);
}
});
return allChilds;
}
Is there any way to overcome this problem so that the function will return after the completion of the event?
ok , you are returning allchilds before the Result Event. You erase the original question ;) , so i dont remember if your problem was this.
Try to split the function : First the request, then get the value of allChild.
and yes ... is better to write (and paste) good formatted code : its easier to understand.
I'm pretty positive what I want to do isn't possible with ActionScript, but it would be nice to be wrong.
I need to pass a variable reference to a function, and have the function change the value of the variable.
So, simplified and not in completely correct syntax, something like this:
function replaceValue(element:*, newValue:String):void
{
element = newValue;
}
var variableToModify:String = "Hello";
replaceValue(variableToModify, "Goodbye");
trace(variableToModify) // traces value of 'Hello', but want it to trace value of 'Goodbye'
Of course, in the replaceValue function, element is a new reference to fungibleValue (or, rather, a new reference to fungibleValue's value). So, while element gets set to the value of newValue, fungibleValue does not change. That's expected but totally not what I want, in this case.
There's a similar question, for Ruby, here Changing value of ruby variables/references
As the question points out, Ruby has a way to accomplish this. BUT is there any way to do this in ActionScript?
If so, it's going to make something stupid a lot easier for me.
No it's not possible the function will always get the value and not the reference. But if you are able to call replaceValue why not returning the new value from your function :
function replaceValue(element:*, newValue:String):String
{
// .. do your work
return newValue;
}
var variableToModify:String = "Hello";
variableToModify = replaceValue(variableToModify, "Goodbye");
trace(variableToModify)
If you pass an Object or a Class, you can modify one fiels based on his name as :
function replaceValue(base:Object, fieldName:String, newValue:String):void {
// do your work
base[fieldName] = newValue;
}
var o:Object={ variableToModify:"Hello" };
replaceValue(o, "variableToModify", "Goodbye");
trace(o.variableToModify);
Should be easy. I have an object. I want to modify it, but before i do I want to save a copy of it that I can go back to. I tried setting copy = original but when i modify the attributes of the original the copy also shows the changes. I am assuming this is because in actionscript any time you assign, it really just stores a reference to the original object. So whats the best way for me to store a copy of the original object for later use?
var newObj:Object = Object(ObjectUtil.copy(oldObj));
"Copies the specified Object and returns a reference to the copy. The copy is made using a native serialization technique. This means that custom serialization will be respected during the copy.
This method is designed for copying data objects, such as elements of a collection. It is not intended for copying a UIComponent object, such as a TextInput control. If you want to create copies of specific UIComponent objects, you can create a subclass of the component and implement a clone() method, or other method to perform the copy."
http://livedocs.adobe.com/flex/3/langref/mx/utils/ObjectUtil.html#copy()
What you are looking for is a deep copy of the object rather then passing by reference. I found the answer here which uses the new ByteArray class in AS3:
http://www.kirupa.com/forum/showthread.php?p=1897368
function clone(source:Object):* {
var copier:ByteArray = new ByteArray();
copier.writeObject(source);
copier.position = 0;
return(copier.readObject());
}
Which you then use like this:
newObjectCopy = clone(originalObject);
Cheers!
// duplicate any given Object (not MCs)
Object.prototype.copy = function()
{
ASSetPropFlags(Object.prototype,["copy"],1);
var _t = new this.__proto__.constructor(this) //
for(var i in this){
_t[i] = this[i].copy()
}
return _t
};
Usage
x = ["1","2","3",[4,5],[{a:1,b:2}]]
y = x.copy()
y[0] = 0
y[3][0]="d"
trace(x)
trace(y)