creationPolicy vs Binding

I just read a comment on an article I wrote a few years ago, creationPolicy vs. Form Data. The commenter suggested that the Save button must be able to read the values from the controls, even if those controls haven’t been created – probably to make the code easier to write or at least consistent.

I disagree with this, but after reading that article again, I see that I could have given more information to support my position.


The article suggests using a <mx:Model> to hold the data and then use data binding to transfer the information from the model to the UI controls. That’s fine for presenting the information, but it doesn’t help when you to save the information.

ActionScript 3 Approach

Here’s a different approach that works better with ActionScript 3 (for Flex 2 or Flex 3). Let’s suppose you have an Accordion with two forms: Payment Information and Shipping Address. Let’s also suppose you have two ActionScript classes that correspond to these forms: PaymentInfo and ShippingAddress. Here’s the definition of the PaymentInfo class:

// file: PaymentInfo.as
package mydata
{
[Bindable]
public class PaymentInfo
{
public var cardType:String;
public var cardNumber:String;
public var expireDate:Date;
}
}

Here’s the definition of the ShippingAddress class:

// file: ShippingAddress.as
package mydata
{
[Bindable]
public class ShippingAddress    {
public var firstName:String;
public var lastName:String;
public var street:String;
public var city:String;
public var state:String;
public var zipCode:String;
}
}

These look like ordinary ActionScript classes, but notice the [Bindable] meta tag above the class definition? That tag tells the compiler that all public properties can be used in data-binding. It is a short-cut to putting [Bindable] before each public variable.

In the Form to be used for the Payment Information you may have controls like this one to get the credit card number:

<mx:TextInput id="creditCardNumber" />

Since you want the PaymentInfo’s cardNumber property to appear in the TextInput, you can use data-binding to associate the property with the field:

<mx:TextInput id="creditCardNumber" text="{data.cardNumber}" />

That’s great for showing the credit card number if the value already exists. But how about saving that information?

Binding Tag

What you want to do is a “reverse” data-binding. Right now the {data.cardNumber} binding is one-way: whatever appears in the PaymentInfo’s cardNumber property appears in the TextInput control. What you’d like is that if you change the value in the UI control to be automatically copied back into the PaymentInfo.

You can do this by using the <mx:Binding> tag. Here’s how to do that for the card number:

<mx:Binding source="creditCardNumber.text" destination="data.cardNumber" />

Any change made to the text property of the creditCardNumber TextInput control is reflected back to the cardNumber property of the PaymentInfo class instance for this Form.

Note: You can also do this type of binding in ActionScript using the mx.binding.utils.BindingUtils class.

Example

Picture this: the Payment Information form appears (blank). You fill in the fields and pick Save. The Save button’s code does not have to access the UI controls at all: it saves the contents of the PaymentInfo class because the Binding took care of transferring the data from the control back to the data class.

<mx:Script><![CDATA[
[Bindable] private var payment:PaymentInfo; // remember to create an instance using the new operator
[Bindable] private var shipping:ShippingAddress; // remember to create an instance using the new operator
]]></mx:Script>

<mx:Accordion>
<forms:PaymentInfoForm data="{payment}" />
<forms:ShippingForm data="{shipping}" />
</mx:Accordion>

Now suppose the Shipping Address were used in the same way, but in this case, the user never opened that form. Since the Save button code is not accessing any of the UI controls on the form, only the ShippingAddress properties, it doesn’t matter if the UI controls were ever created.

In the above code example, the Binding tags will transfer changes to the controls in the PaymentInfoForm to the payment variable. Changes to the controls in the ShippingForm (if created by the user visiting it in the Accordion) will likewise be transferred to the shipping variable.

The Save button code then saves the contents of the payment and shipping variables.

Summary

Using the Binding tag to “reverse” data-binding on editable controls will make your code easier to write, understand, and more reliable. You won’t have to worry if user’s never touch containers on controls like Accordion or TabNavigator. And if the user does visit a form, data binding will populate the UI controls and Binding will read them.

And yes, if you have 100 UI controls and fields you will need 100 Binding tags.

9 Responses to creationPolicy vs Binding

  1. Ben says:

    Very nice. So simple but never really thought to do it that way before.

  2. Thom Blake says:

    I had been thinking about this, but I was wondering whether the seeming circular reference would cause any issues.

  3. Gareth says:

    If you create a “new” instance of the mydata class somewhere in your page, don’t you have to rebind everything? I had this occur on one project I was working on and couldn’t figure out why all of my databinding was lost (using BindingUtils via AS). I re-ran the binding if I created a new instance and all was good again. It really is a nice way of binding data, though.
    ——-
    Peter: That’s correct. The binding is to the instance.

  4. Nick V says:

    This works fine if you have one shipping and one billing VO. I started with this approach some time ago, and found that if you have to change the object the ui controls bind to, this approach does not work.
    The problem is once you bind the ui to a particular object, there is no way to switch the reverse bind to another VO.
    The typical use case for this is the user has an array of addresses they need to choose from for the billing and shipping addresses, or an “address book”.
    ———————
    Peter: You do have to recreate the bindings if you change instances. But what about leaving the instance in place and copying the VO of interest into the one being used for binding? Your VO class could have a static copy function for this purpose.

  5. Tink says:

    Hey Peter

    Do you have any thoughts on the overheads when using Binding. especially if you have a load of different ValueObject class types with public properties such as those in your example, and your create hundreds or each.
    ————
    Peter: The binding code does add some overhead; how much I’m not certain.

  6. sultan says:

    Very nice. Tellement simple, mais jamais vraiment pensé à le faire de cette façon avant

  7. Arnoud Bos says:

    Hi Peter,

    This is a nice read. It raises some questions though:

    1) I’m using cairngorm for most of my development. I bind model vars on fom items just like you do. But if I do the bidirectional binding the view sets the model, right? Strict mvc dictates that only the controller updates the model. Just wondered what’s your opinion on that. Is this approach viable in a cairngorm structure? I mean using a framework shouldn’t get in the way. It should help.

    2) I don’t see how client side form validation (with validators etc. attached to the form could work if the form ui doesn’t exist at all). Does this mean you use another way of validating? For exmple for each VO a VOValidator which checks the validity of the values of the VO? Or do you suggest to do validating only on the server? (which is always needed of course). Somehow i have the feeling you should only update the model if the contents of the form are validated.

    Arnoud Bos
    —————–
    Peter: I agree about the MVC paradigm, but sometimes making code easier to read and implement takes precedence. I don’t use Cairngorm so I’m not sure how you would incorporate this.

    Flex “validation” is meant to be purely visual. If the UI controls don’t exist, then there is no need for Flex validation. You would have to do your own validation, of course.

  8. m7mmad says:

    Really simple , Thanks

  9. دردشة says:

    Really simple , Thanks