Here’s a problem that occurs often in UI development; You have a model and you want to do changes that can be ‘cancelled’ or reverted back to it’s original. You don’t want to modify the model directly because those are normally the values that the server gives you and you wouldn’t want to be off-sync with the server if you’re doing polling or pushing data retrieval.
What’s the solution? Since it’s the actual components doing a change, you want them to keep state because the components know when to update or reset. How you implement this solution is up to you, but here’s a utility that might help; ObjectUtil.
ObjectUtil is a class (under the mx.utils package) that helps you do various object operations that are particularly useful in this case. One function especially, ‘copy’, is used to create a straight memory to memory copy (also called a ‘deep copy’) of your object into a new variable. This can save a lot of time and lines of code to do an actual copy manually, which I’ve done in my early days of Flex before I found out about this class. But be warned, since this is a deep copy, it will copy over everything in it. If you were to say, copy an ArrayCollection, it will copy the collection, all the elements within it, and the refering objects within those elements which can be quite costly. It is best used for a self contained data model classes, that way it copies only small bits of data that’s needed for a specific component.
Here’s a quick and dirty example that one could use for their own purposes. Notice how I use an ‘edited’ flag so that new data coming in doesn’t affect the changes done by the user until the user is done. This is not the best example, but it does give an idea of how to use ObjectUtil.
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import com.codemonkeycreative.delegates.SomeDelegate;
import com.codemonkeycreative.model.entity.SomeModel;
import mx.utils.ObjectUtil;
[Bindable] private var _data:SomeModel;
private var _currentData:SomeModel;
private var _min:Number;
private var _max:Number;
private var _edited:Boolean = false;
[Bindable]
public function get dataProvider():SomeModel
{
return this._currentData;
}
public function set dataProvider(value:SomeModel):void
{
this._currentData = value;
if(!this._edited)
{
this._data = SomeModel(ObjectUtil.copy(this._currentValue));
}
}
private function reset():void
{
this._data = SomeModel(ObjectUtil.copy(this._currentValue));
this._edited = false;
}
private function save():void
{
// Call your Delegate/Webservice here with the new value
// Making this generic since there's many ways to implement
SomeDelegate.saveValue(this._data);
this._currentData = this._data;
// Reset form
this.reset();
}
private function onChange():void
{
this._edited = true;
this._data.value = stepper.value;
}
]]>
</mx:Script>
<mx:HBox>
<mx:Label text="{stepper.value}" />
<mx:NumericStepper id="stepper" value="{this._data.value}" stepSize="1"
minimum="{this._data.min}" maximum="{this._data.max}" change="onChange" />
</mx:HBox>
<mx:HBox enabled="{this._edited}">
<mx:Button label='Reset' click="reset()" />
<mx:Button label='Save' click="save()" />
</mx:HBox>
</mx:VBox>


